0
votes

Hi I am using react redux with toolkit and I am wondering why my state is not getting updated despite dispatching the action with the right payload. I am trying to update the user state in redux from null to an object containing the user data when they are logged in and vice versa. Am I correctly updating the state in an 'immutable' way in this case? Thanks for any help in advance.

UPDATE: It seems that it works when i change the initialState to an object refer to @aboutcoding answer. However my use case requires it to be null initially. I tried making state = 1 in my reducer function just to test whether it will update but it also doesn't. I am not sure why just equating state to a new value doesn't work since null is considered primitive which is immutable by default.

Here is the slice.js code:

import {createSlice} from '@reduxjs/toolkit';

export const userSlice = createSlice({
  name: 'user',
  initialState: null,
  reducers: {
    updateUser: (state, action) => {
      state = action.payload;
    },
  },
});

export const {updateUser} = userSlice.actions;

export default userSlice.reducer;

Here is my store.js code:

import {createSlice} from '@reduxjs/toolkit';

export const userSlice = createSlice({
  name: 'user',
  initialState: null,
  reducers: {
    updateUser: (state, action) => {
      state = action.payload;
    },
  },
});

export const {updateUser} = userSlice.actions;

export default userSlice.reducer;

App.js where the action is disptached:

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow strict-local
 */
import 'react-native-gesture-handler';
import React, {useState, useEffect} from 'react';
import auth from '@react-native-firebase/auth';
import {StatusBar} from 'react-native';
import {NavigationContainer} from '@react-navigation/native';
import LoginStack from './src/navigation/loginStack';
import DrawerNavigator from './src/navigation/drawer';
import {useDispatch, useSelector} from 'react-redux';
import {updateUser} from './src/redux/userSlice';

export default function App() {
  // Set an initializing state while Firebase connects
  const user = useSelector((state) => state.user);
  const [initializing, setInitializing] = useState(true);
  const dispatch = useDispatch();
  // Handle user state change
  // eslint-disable-next-line no-shadow
  function onAuthStateChanged(user) {
    if (user) {
      const userData = {
        displayName: user.displayName,
        email: user.email,
        emailVerified: user.emailVerified,
      };
      dispatch(updateUser(userData));
    } else {
      dispatch(updateUser(user));
    }

    if (initializing) {
      setInitializing(false);
    }
  }

  useEffect(() => {
    const subscriber = auth().onAuthStateChanged(onAuthStateChanged);
    return subscriber;
  });

  if (initializing) {
    return null;
  }

  return (
    <>
      <StatusBar barStyle="default" />
      {!user ? (
        <>
          <NavigationContainer>
            <LoginStack />
          </NavigationContainer>
        </>
      ) : (
        <>
          <NavigationContainer>
            <DrawerNavigator />
          </NavigationContainer>
        </>
      )}
    </>
  );
}

My react dev tools shows that state did not changed after dispatching the action: enter image description here enter image description here

2

2 Answers

1
votes

try this:

{...action.payload}

As I always initialising my state I'm not sure you need to do it too. So try this below:

Update:

import {createSlice} from '@reduxjs/toolkit';

initialstate = {
  displayName: "",
  email: "",
  emailVerified: ""
}

export const userSlice = createSlice({
  name: 'user',
  initialState,
  reducers: {
    updateUser: (state, action) => {
      state = {...action.payload};
    },
  },
});

export const {updateUser} = userSlice.actions;

export default userSlice.reducer;

You could also try to update your React DevTools. It seem to be out of the date. Maybe it's not working properly.

0
votes

Have a try with the below method.

Like:

updateUser: (state, action) => {
  state = {
      ...action.payload
  }
},

Mutating the state will not reflect the changes at render-cycle.