۱۴۰۴/۰۸/۰۴ Nebular

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>
  );
}

🔹 نکات کلیدی

  1. Context + useReducer معادل Redux ساده بدون middleware است.
  2. تمام کامپوننت‌های زیر CounterProvider می‌توانند به state و dispatch دسترسی داشته باشند.
  3. بدون نیاز به نصب هیچ کتابخانه اضافی (redux/@reduxjs/toolkit)
  4. مناسب پروژه‌های کوچک و متوسط. برای پروژه‌های خیلی بزرگ یا async پیچیده، Redux Toolkit یا RTK Query حرفه‌ای‌تر هست.
Accept Cookies
Accept Cookies
[your-shortcode]