24
loading...
This website collects cookies to deliver better user experience
type State = { counter: number };
type Action = { type: "INCREMENT" } | { type: "DECREMENT" };
const initialState: State = { counter: 0 };
const reducer = (state: State, action: Action): State => {
switch (action.type) {
case "INCREMENT":
return {
...state,
counter: state.counter + 1
};
case "DECREMENT":
return {
...state,
counter: state.counter - 1
};
default:
return state;
}
};
useReducer
hook that returns current state paired with dispatch
method that's responsible for executing actions, but in order to use it all across our application we need some place where we can store it. For that, we will use React context.import {
createContext,
Dispatch,
ReactNode,
useContext,
useReducer
} from "react";
const StoreContext = createContext<[State, Dispatch<Action>]>([
initialState,
() => {} // initial value for `dispatch`
]);
export const StoreProvider = ({ children }: { children: ReactNode }) => (
<StoreContext.Provider value={useReducer(reducer, initialState)}>
{children}
</StoreContext.Provider>
);
export const useStore = () => useContext(StoreContext);
useStore
hook we created using useContext
. This hook will allow us to access state
and dispatch
in each child component of StoreProvider
.StoreProvider
in render
method which will cause our state to be accessible globally, but I would like to note that you should keep your state as close to where it's needed as possible, since updates in context will trigger re-render in each of the providers' child components which might lead to performance issues once your application grows bigger.import { render } from "react-dom";
import App from "./App";
import { StoreProvider } from "./store";
const rootElement = document.getElementById("root");
render(
<StoreProvider>
<App />
</StoreProvider>,
rootElement
);
useStore
hook in action.export default function App() {
const [state, dispatch] = useStore();
return (
<div className="container">
<button onClick={() => dispatch({ type: "INCREMENT" })}>Increment</button>
<button onClick={() => dispatch({ type: "DECREMENT" })}>Decrement</button>
<p>Counter: {state.counter}</p>
</div>
);
}