۱۴۰۴/۰۸/۰۴
Context و Reducer
۱️⃣ ساخت Context و Reducer
// context/CounterContext.tsx
import React, { createContext, useReducer, ReactNode, useContext } from "react";
// Types
type State = { count: number };
type Action = { type: "INCREMENT" | "DECREMENT" | "RESET" };
// Initial state
const initialState: State = { count: 0 };
// Reducer
const counterReducer = (state: State, action: Action): State => {
switch (action.type) {
case "INCREMENT":
return { count: state.count + 1 };
case "DECREMENT":
return { count: state.count - 1 };
case "RESET":
return { count: 0 };
default:
return state;
}
};
// Contexts
const CounterStateContext = createContext<State | undefined>(undefined);
const CounterDispatchContext = createContext<React.Dispatch<Action> | undefined>(undefined);
// Provider
export const CounterProvider = ({ children }: { children: ReactNode }) => {
const [state, dispatch] = useReducer(counterReducer, initialState);
return (
<CounterStateContext.Provider value={state}>
<CounterDispatchContext.Provider value={dispatch}>
{children}
</CounterDispatchContext.Provider>
</CounterStateContext.Provider>
);
};
// Custom hooks
export const useCounterState = () => {
const context = useContext(CounterStateContext);
if (!context) throw new Error("useCounterState must be used within CounterProvider");
return context;
};
export const useCounterDispatch = () => {
const context = useContext(CounterDispatchContext);
if (!context) throw new Error("useCounterDispatch must be used within CounterProvider");
return context;
};
۲️⃣ Wrap کردن اپلیکیشن با Provider
// main.tsx یا index.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { CounterProvider } from "./context/CounterContext";
ReactDOM.createRoot(document.getElementById("root")!).render(
<CounterProvider>
<App />
</CounterProvider>
);
۳️⃣ استفاده در کامپوننت Counter
import React from "react";
import { useCounterState, useCounterDispatch } from "./context/CounterContext";
export default function Counter() {
const { count } = useCounterState();
const dispatch = useCounterDispatch();
return (
<div style={{ textAlign: "center" }}>
<h1>Count: {count}</h1>
<button onClick={() => dispatch({ type: "INCREMENT" })}>Increment</button>
<button onClick={() => dispatch({ type: "DECREMENT" })}>Decrement</button>
<button onClick={() => dispatch({ type: "RESET" })}>Reset</button>
</div>
);
}
🔹 نکات کلیدی
- Context + useReducer معادل Redux ساده بدون middleware است.
- تمام کامپوننتهای زیر
CounterProviderمیتوانند به state و dispatch دسترسی داشته باشند. - بدون نیاز به نصب هیچ کتابخانه اضافی (
redux/@reduxjs/toolkit) - مناسب پروژههای کوچک و متوسط. برای پروژههای خیلی بزرگ یا async پیچیده، Redux Toolkit یا RTK Query حرفهایتر هست.
Accept Cookies
[your-shortcode]