Next.js Discord

Discord Forum

ContextAPI with reducer not working

Unanswered
Teddy Roosevelt Terrier posted this in #help-forum
Open in Discord
Teddy Roosevelt TerrierOP
When I dispatch an action I do not receive any data in my reducer. I am wrapping my head over it for the last 3 hours! Please help!

2 Replies

Teddy Roosevelt TerrierOP
// CalculatorComponent

"use client";

import { useSearchParams } from "next/navigation";
import Calculator from "@/components/calculator/Index";
import { CalculatorContextProvider, useCalculatorContext } from "@/context";
import { useEffect } from "react";
import { CalculatorConfig } from "@/types";

function CalculatorComponent() {
  const calculatorContext = useCalculatorContext();
  const query = useSearchParams();
  const encodedConfigString = query.get("config") as string;
  const decodedConfigString = decodeURIComponent(encodedConfigString).replace(
    "'",
    ""
  );

  const decodedConfig = JSON.parse(decodedConfigString) as CalculatorConfig;

  useEffect(() => {
    calculatorContext.dispatch({
      type: "SET_CONFIG",
      payload: {
        currency: decodedConfig.currency,
        theme: {
          primaryBackgroundColor: decodedConfig.theme?.primaryBackgroundColor,
        },
      },
    });
  }, [decodedConfig, calculatorContext]);

  // Example of dynamically setting CSS variables (commented out in your code)
  useEffect(() => {
    if (calculatorContext.calculatorConfig.theme) {
      const theme = calculatorContext.calculatorConfig.theme;
      for (const themeProperty in theme) {
        const cssKey = `--${themeProperty}`;
        document.documentElement.style.setProperty(
          cssKey,
          theme[themeProperty]
        );
      }
    }
  }, [calculatorContext.calculatorConfig.theme]);

  return <Calculator currency={calculatorContext.calculatorConfig.currency} />;
}

export default function Home() {
  return (
    <CalculatorContextProvider>
      <CalculatorComponent />
    </CalculatorContextProvider>
  );
}
import {
  CalculatorContextProviderProps,
  CalculatorReducerAction,
  CurrencyCode,
  CalculatorConfig,
} from "@/types";
import { camelToHyphen } from "@/utils/helpers";
import { createContext, useContext, useReducer } from "react";

const defaultConfig: CalculatorConfig = {
  currency: CurrencyCode.EUR,
};

function calculatorReducer(
  state: CalculatorConfig,
  action: CalculatorReducerAction
) {
  console.log({ action });
  switch (action.type) {
    case "SET_CONFIG":
      // set theme
      if (action.payload.theme && Object.values(action.payload.theme).length) {
        Object.entries(action.payload.theme).forEach(([key, value]) => {
          const configKey = camelToHyphen(key);
          document.documentElement.style.setProperty(
            `--${configKey}`,
            value as string
          );
        });
      }

      return { ...state, currency: action.payload.currency };
    default:
      return state;
  }
}

const CalculatorContext = createContext<{
  calculatorConfig: CalculatorConfig;
  dispatch: React.Dispatch<CalculatorReducerAction> | null;
}>({
  calculatorConfig: defaultConfig,
  dispatch: null,
});

export function CalculatorContextProvider({
  children,
}: CalculatorContextProviderProps) {
  const [calculatorConfig, dispatch] = useReducer(
    calculatorReducer,
    defaultConfig
  );

  return (
    <CalculatorContext.Provider value={{ calculatorConfig, dispatch }}>
      {children}
    </CalculatorContext.Provider>
  );
}

export function useCalculatorContext() {
  const context = useContext(CalculatorContext);

  if (!context.dispatch) {
    throw new Error(
      "useCalculatorContext must be used within a CalculatorContextProvider"
    );
  }

  return context;
}