Closed as not planned
Closed as not planned
Description
openedon May 15, 2024
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>
);
}
Thank you!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Metadata
Assignees
Labels
No labels