'useSelector doesn't update value in Next.js

I have a problem, createAsyncThunk function makes request to server (axios) and then get data, after that extraReducers handle builder.addCase in it and makes state.value = action.payload, then console.log(state.value) writes value from server. Great! It works, but when I use useSelector it sees 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 doesn't give me updated value.

Slice code

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;

configurate store

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);

hooks for TypeScript

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 useSelector (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: {}
  }
})


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source