ContextAPI with reducer not working
Unanswered
Teddy Roosevelt Terrier posted this in #help-forum
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;
}