ideas
ideas copied to clipboard
useLocalStorageReducer
Reducer with state synced with localStorage. Would be great for syncing state between tabs and sessions.
Basic initial Implementation would look like this
import React, { useReducer, useEffect } from "react";
import { render } from "react-dom";
import useLocalStorage from '@rehooks/local-storage';
function useLocalStorageReducer({ reducerKey, transformer }, reducer, initialState, initialAction) {
let localState = useLocalStorage(reducerKey);
if (localState) {
localState = JSON.parse(localState);
localState = transformer(localState);
} else {
localState = initialState;
}
const [state, dispatch] = useReducer(reducer, localState, initialAction);
useEffect(
() => {
localStorage.setItem(reducerKey, JSON.stringify(state));
},
[state]
);
return [state, dispatch];
}
const initialState = { count: 0 };
function reducer(state, action) {
switch (action.type) {
case "reset":
return { count: action.payload };
case "increment":
return { count: state.count + 1 };
case "decrement":
return { count: state.count - 1 };
default:
return state;
}
}
function transformer(state) {
return { ...state, count: parseInt(state.count) };
}
function Counter({ initialCount }) {
const [state, dispatch] = useLocalStorageReducer(
{ reducerKey: "counter", transformer },
reducer,
initialState
);
return (
<div>
Count: {state.count}
<button onClick={() => dispatch({ type: "reset", payload: initialCount })}>Reset</button>
<button onClick={() => dispatch({ type: "increment" })}>+</button>
<button onClick={() => dispatch({ type: "decrement" })}>-</button>
</div>
);
}
function App() {
let name = useLocalStorage("name");
return (
<div>
<h1>{name}</h1>
<Counter initialCount={0} />
</div>
);
}
Not sure about one thing, this won't update the reducerState once it is mounted. Need to investigate that.