Skip to content

Error: could not find react-redux context value; please ensure the component is wrapped in a <Provider> #4410

Closed as not planned

Description

I'm having some problems learning Redux, and I'm currently using React 18 + Next 14 + Typescript + App Router.

When I integrate as per the development documentation, it always prompts me for this error, even if I copy the code in the example.

// store.ts
import { configureStore } from "@reduxjs/toolkit";
import demoReducer from "./features/demo/demoSlice";
export const makeStore: any = () => {
	return configureStore({
		reducer: {
			demo: demoReducer,
		},
	});
};

export type AppStore = ReturnType<typeof makeStore>;
export type RootState = ReturnType<AppStore["getState"]>;
export type AppDispatch = AppStore["dispatch"];
// hooks.ts
import { useDispatch, useSelector, useStore } from "react-redux";
import type { AppStore, AppDispatch, RootState } from "./store";

export const useAppDispatch = useDispatch.withTypes<AppDispatch>();
export const useAppSelector = useSelector.withTypes<RootState>();
export const useAppStore = useStore.withTypes<AppStore>();
// demoSlice.ts
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import type { RootState } from "../../store";

const initialState = {
	value: 0,
};

export const demoSlice = createSlice({
	name: "demo",
	initialState,
	reducers: {
		increment: (state) => {
			state.value += 1;
		},
		decrement: (state) => {
			state.value -= 1;
		},
		incrementByAmount: (state, action: PayloadAction<number>) => {
			state.value += action.payload;
		},
		initializeCount: (state, action: PayloadAction<number>) => {
			state.value = action.payload || 0;
		},
	},
});

export const { increment, decrement, incrementByAmount, initializeCount } = demoSlice.actions;

export const selectCount = (state: RootState) => state.demo.value;

export default demoSlice.reducer;
// StoreProvider.tsx
"use client";
import { useRef } from "react";
import { Provider } from "react-redux";
import { makeStore, AppStore } from "./services/stores/store";

import { initializeCount } from "./services/stores/features/demo/demoSlice";

export default function StoreProvider({
	data,
	children,
}: {
	data: any;
	children: React.ReactNode;
}) {
	const storeRef = useRef<AppStore | null>(null);
	if (!storeRef.current) {
		storeRef.current = makeStore();
		storeRef.current.dispatch(initializeCount(data));
	}

	return <Provider store={storeRef.current}>{children}</Provider>;
}
// OpenMenuButton.tsx
"use client";
import { useRef } from "react";
import {
	useAppSelector,
	useAppDispatch,
	useAppStore,
} from "@services/stores/hooks";
import {
	increment,
	decrement,
	incrementByAmount,
	initializeCount,
} from "@/app/services/stores/features/demo/demoSlice";

export default function OpenMenuButton() {
	const store = useAppStore();
	const initialized = useRef(false);

	if (!initialized.current) {
		store.dispatch(initializeCount(0));
		initialized.current = true;
	}

	const count = useAppSelector((state) => {
		console.log(state.demo.value);
		return state.demo.value;
	});
	const dispatch = useAppDispatch();

	return (
		<div>
			<div>
				<button onClick={() => dispatch(increment())}>Increment</button>
				<span>{count}</span>
				<button onClick={() => dispatch(decrement())}>Decrement</button>
			</div>
		</div>
	);
}

image

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions