useReducer और Context को मिलाना
In this page:
const StateContext = createContext();
const DispatchContext = createContext();
function Provider({ children }) {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<StateContext.Provider value={state}>
<DispatchContext.Provider value={dispatch}>
{children}
</DispatchContext.Provider>
</StateContext.Provider>
);
}
useReducer को Context के साथ क्यों Combine करें
useReducer state-update logic को एक function में centralize करता है जो हर possible action handle करता है, जो कई separate useState calls से बेहतर scale करता है जब एक app में कई related pieces of state हों।
इसे Context के साथ pair करना state और dispatch function दोनों को tree में कहीं भी available कराता है।
उदाहरण: Why Combine useReducer with Context
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
function reducer(state, action) {
switch (action.type) {
case "increment": return { count: state.count + 1 };
case "decrement": return { count: state.count - 1 };
default: return state;
}
}
function App() {
const [state, dispatch] = React.useReducer(reducer, { count: 0 });
return <button onClick={() => dispatch({ type: "increment" })}>Count: {state.count}</button>;
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>
Context के through State और Dispatch Share करना
एक Provider component एक बार useReducer call करता है और resulting state और dispatch function दोनों को एक Context के through नीचे pass करता है। कोई भी descendant component फिर current state पढ़ सकता है और actions dispatch कर सकता है, उन्हें props के रूप में pass किए बिना।
उदाहरण: Sharing State and Dispatch via Context
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
const CartContext = React.createContext();
function reducer(state, action) {
if (action.type === "add") return { items: [...state.items, action.item] };
return state;
}
function CartProvider({ children }) {
const [state, dispatch] = React.useReducer(reducer, { items: [] });
return <CartContext.Provider value={{ state, dispatch }}>{children}</CartContext.Provider>;
}
function AddButton() {
const { dispatch } = React.useContext(CartContext);
return <button onClick={() => dispatch({ type: "add", item: "Book" })}>Add Book</button>;
}
function App() {
return <CartProvider><AddButton /></CartProvider>;
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>
किसी भी Component से Shared State पढ़ना
एक बार reducer और Context wire हो जाने पर, Provider के अंदर nested कोई भी component useContext call करके live state पढ़ सकता है, उस component से पूरी तरह independent जिसने last change trigger किया था।
यही इस pattern को UI के unrelated parts में shared state के लिए useful बनाता है।
उदाहरण: Reading Shared State from Any Component
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
const CartContext = React.createContext();
function reducer(state, action) {
if (action.type === "add") return { items: [...state.items, action.item] };
return state;
}
function CartProvider({ children }) {
const [state, dispatch] = React.useReducer(reducer, { items: [] });
return <CartContext.Provider value={{ state, dispatch }}>{children}</CartContext.Provider>;
}
function ItemCount() {
const { state } = React.useContext(CartContext);
return <p>Items in cart: {state.items.length}</p>;
}
function App() {
return <CartProvider><ItemCount /></CartProvider>;
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>
- Actions को उनके type string में typos के साथ dispatch करना, जिन्हें reducer silently ignore कर देता है अगर कोई matching case न हो।
- Reducer के switch statement में default case भूल जाना, जो unhandled actions के लिए undefined return कर सकता है।
- State और dispatch दोनों को बिना memoize किए एक ही context value में रखना, जो किसी भी change पर हर consumer को re-render कराता है।
- useReducer एक reducer function और dispatched actions के through state manage करता है, Redux के core idea जैसा।
- इसे Context के साथ combine करना current state और dispatch function दोनों को app-wide share करता है।
- Components useContext के through state पढ़ते हैं और dispatch({ type: '...' }) call करके changes trigger करते हैं।
- यह pattern कई related actions वाले state के लिए अच्छी तरह scale करता है, जैसे एक shopping cart या एक multi-field form।
useReducer के लिए React 16.8 (Hooks introduction) से उपलब्ध है; Context API React 16.3 से stable है।
Chapter Quiz — Complete all 10 topics to unlock
0/10 topics done
Complete these topics first: