next-redux-wrapper
next-redux-wrapper copied to clipboard
Redux toolkit. reducers and extraReducer is work but useSelector (for type) dont give updated state.
Describe the bug
i have createAsyncThunk function. It makes request to server (axios) and then get data, after that extraReducers handle builder.addCase in it makes state.value = action.payload, then consol.log(state.value) writes value from server. Great! Its work but!! when i use useSelector it see existing value from initialState but get value only when it was first time initialized(null or just []) not updated after dispatch in wrapper.getServerSIdeProps . Same with just reducers and function in. it It works change state (console.log write it) but useSelector dont give me updated value
Code
Slice
import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit';
import axios from 'axios';
import { HYDRATE } from 'next-redux-wrapper';
// types
import { IInitialStateV1 } from '../types/store';
import { ITrack } from '../types/tracks/track';
export const fetchData = createAsyncThunk('main/fetchData', async (): Promise<ITrack[]> => {
const { data } = await axios.get<ITrack[]>('http://localhost:5000/track');
return data;
})
const initialState: IInitialStateV1 = {
pause: true,
currentTime: 0,
volume: 0,
duration: 0,
active: null,
tracks: [],
}
export const mainSlice = createSlice({
name: 'main',
initialState,
reducers: {
setPause(state, action: PayloadAction<boolean>) {
state.pause = action.payload;
},
setTime(state, action: PayloadAction<number>) {
state.currentTime = action.payload;
},
setVolume(state, action: PayloadAction<number>) {
state.volume = action.payload;
},
setDuration(state, action: PayloadAction<number>) {
state.duration = action.payload;
},
setActive(state, action: PayloadAction<ITrack>) {
state.active = action.payload;
state.currentTime = 0;
state.duration = 0;
}
},
extraReducers: (builder) => {
// [HYDRATE]: (state, action) => {
// return {
// ...state,
// ...action.payload,
// }
// },
// [fetchData.fulfilled.toString()]: (state, action: PayloadAction<ITrack[]>) => {
// state.tracks = action.payload;
// }
builder.addCase(HYDRATE, (state, action: any) => {
return {
...state,
...action.payload,
}
}).addCase(fetchData.fulfilled, (state, action: PayloadAction<ITrack[]>) => {
// return {
// ...state,
// ...action.payload,
// }
state.tracks = action.payload;
});
}
})
export const { setPause, setTime, setVolume, setDuration, setActive } = mainSlice.actions;
export default mainSlice.reducer;
Index
import { AnyAction, configureStore, ThunkDispatch } from '@reduxjs/toolkit';
import { createWrapper, MakeStore, Context } from 'next-redux-wrapper';
import mainRed from './index';
const makeStore = () => configureStore({
reducer: {
main: mainRed
},
})
type AppStore = ReturnType<typeof makeStore>;
export type RootState = ReturnType<AppStore['getState']>;
export type AppDispatch = AppStore['dispatch'];
export type NextThunkDispatch = ThunkDispatch<RootState, void, AnyAction>;
export const wrapper = createWrapper<AppStore>(makeStore);
edited hooks
import { useDispatch, useSelector, TypedUseSelectorHook } from "react-redux";
import { RootState, AppDispatch } from "../store/reducer";
export const useTypeSelector: TypedUseSelectorHook<RootState> = useSelector;
export const useTypeDispath = ()=> useDispatch<AppDispatch>();
getServerSIdeProps and useSelectore ( in page)
import { Container, ListItem, Stack, Box, Button } from "@mui/material";
import TrackList from "../../components/TrackList";
// interfaces
import { ITrack } from "../../types/tracks/track";
// import hooks
import { useRouter } from "next/router";
import { useTypeSelector } from "../../hooks/useTypeSelector";
// wrapper
import { NextThunkDispatch, wrapper } from "../../store/reducer";
import { fetchData, setVolume } from "../../store";
export default function Index(): JSX.Element {
const router = useRouter();
const tracks: ITrack[] = useTypeSelector(state => state.main.tracks);
return (
<div className="main">
<Container >
<Stack marginTop={20} sx={{ backgroundColor: "#C4C4C4", fontSize: '24px', fontWeight: 'bold' }}>
<Box p={5} justifyContent="space-between">
<ListItem>List of Tracks</ListItem>
<Button variant="outlined" sx={{ backgroundColor: 'blue', color: 'white' }} onClick={() => router.push('/tracks/create')} >Upload</Button>
</Box>
<TrackList tracks={tracks} />
</Stack>
</Container>
</div>
)
}
export const getServerSideProps = wrapper.getServerSideProps((store) => async () => {
const dispatch = store.dispatch as NextThunkDispatch;
// dispatch(fetchData());
dispatch(setVolume(2));
return {
props: {}
}
})
Expected behavior
It supposed to dispatch function get value from server and be in useSelector.
Screenshots
If applicable, add screenshots to help explain your problem.
Desktop (please complete the following information):
Windows, OperaGX.
Additional context
Add any other context about the problem here.
I'm facing the same issue. Have you found something?
I'm facing the same issue. Have you found something?
ContextApi instead of next-wrapper-redux
I have the same issue useAppSelector not give any updated value
I'm facing the same issue. Have you found something?
Same issue here. Have you found any solution on this ? :)
I've managed to solve it by copying source code of the module (next-redux-wrapper) to my src folder and referencing from there. It works perfectly. I suspect that problem is somewhere at redux or react-redux. They are not resolved properly or using different versions.
Do yarn why react-redux
and yarn why redux
to see which packages are installed and why, and let me know.
You can set exact version by using resolutions
field in your package.json
.
Hi, action.payload has the state of the whole app, please console.log(action.payload)
in HYDRATE builder, so this builder won't work
builder.addCase(HYDRATE, (state, action: any) => {
return {
...state,
...action.payload,
}
}
try this way state = action.payload.main
and persist the server state or state.currentTime = action.payload.main.currentTime
builder.addCase(HYDRATE, (state, action: any) => {
state = action.payload.main
}
forget about tihs issue. Closed