1

I am working with React Redux, I can't understand why it brings the former state again.

actions.js

export const SET_USER= "SET_USER";

export const setUser = user => ({
  type: SET_USER,
  payload: user
});

reducers.js

import { SET_USER } from "./actions";

const initialState = {
  user: {
    name: '',
    profileId: ''
  }
};

const userReducer = (state = initialState, action) => {
  switch (action.type) {
    case SET_USER: {
      return 
        ...state,
        user: action.payload
      };
    }

    default:
      return state;
  }
}

export default userReducer;

store.js

import AsyncStorage from '@react-native-async-storage/async-storage';
import { persistStore, persistReducer } from 'redux-persist'
import userReducer from './reducers';
import { createStore } from 'redux'

const persistConfig = {
  key: 'root',
  storage: AsyncStorage,
}

const persistedReducer = persistReducer(persistConfig, userReducer)

export const store = createStore(persistedReducer)
export const persistor = persistStore(store)

Home.js

const user = useSelector(state => state.user);

<Text>{user.profileId}<Text>

SecondScreen.js

I refresh user data from server with user.profileId here

const user = useSelector((state) => state.user);
const [profileData, setProfileData] =useState([]);


useEffect(() => {
  console.log("Here I wait updated profileId", user.profileId)
  apiGetProfile();
}, []);

const apiGetProfile = async () => {
  mainAxios
      .get('profiles/' + user.profileId, {})
      .then(function (response) {
        setLoading(false)
        if (response.status == 200) {

          setProfileData(response.data)
        } 
      })
      .catch(function (error) {
        console.log(error);
      });
  };

Settings.js

import { setUser} from './../../reduxStore/actions';
import { useDispatch } from 'react-redux';

const Settings = ({ navigation }) => {
  const changeProfile = id => {     
    dispatch(setUser({ name: "New name", profileId: "new id" }))
  };

}

I change user name and id in settings screen with dispatch, then on Home screen I observe new values but then I move to Second screen I get former old values there.

niphredil
  • 41
  • 4
  • Could you please clarify what do you mean by "former state". If you change name several times Home screen shows the latest and Second screen shows previous change? – dlitsman Mar 21 '23 at 22:22
  • @dlitsman First user.profileId is 11111 when I login app I get 11111 in Home and SecondScreen than go to Settings and change user.profileId to 22222 go back Home user.profileId gives 22222 but when I navigate SecondScreen I get 11111 again, if I close and open app again I get 22222 on Second screen too – niphredil Mar 22 '23 at 05:07
  • Is anything missing from the code for second screen? You seem to only use the user value inside the useEffect hook – David Hall Mar 22 '23 at 06:39
  • The provided code example appears to be incomplete. Please [edit] to include all relevant code in your [mcve]. – Drew Reese Mar 22 '23 at 07:10
  • Edited second screen – niphredil Mar 22 '23 at 08:13

3 Answers3

1

The problem appears to be with you useEffect hook.

The second parameter of the hook is its dependency array - when this array is empty you are telling React to only run the hook on the first render cycle.

Changing your hook to the following should help:

useEffect(() => {
  console.log("Here I wait updated profileId",user.profileId )
}, [user.profileId]);

That said - it isn't clear if there is anything missing from your code. You only havea console.log in useEffect which isn't necessary (you don't need useEffect for this), and useSelector will trigger a re-render, so if you use user.profileId in JSX code I would expect it to update.

David Hall
  • 32,624
  • 10
  • 90
  • 127
0

reducer.js

    import { SET_USER } from "./actions";

    const initialState = {

      user:{
        name:'',
        profileId:''
      }
    };

    const userReducer = (state = initialState, action) => {
      switch (action.type) {
        
        case SET_USER: {
        
          return 
            user: action.payload
          };
        }
        default:
          return state;
      }
    }

    export default userReducer;

Home.js

const  user  = useSelector(state => state.user.profileId);
const [userId,setUserId]=useState(user);

  <Text>{userId}<Text>

SecondScreen.js

 const  user  = useSelector(state => state.user.profileId);

//  useEffect(() => {
    //console.log("Here I wait updated profileId",user.profileId )
  //}, []);//not required useEffect

const [userId,setUserId]=useState(user);

  <Text>{userId}<Text>

if you want to store multiple data then store array of object insted of simple string like this :

const initialState = {    |  const initialState = {
                          |
                          | 
  user:{                  |   user:[{               
    name:'',              |        name:'someName',
    profileId:''          |        profileId:111, 
  }                       |   }]
};                        | };

if you want multiple data then use spread operator in dispatch method like this:

case SET_USER: {               | case SET_USER: { 
      return                   | return {
        ...state,              | ...state,
        user: action.payload   | user: 
                                    [...state.user,action.payload],
      };                       |  }; 
    }                          | }

temperory i have stored single data in your case ,now you can change whatever you want its very simple

Kishan
  • 106
  • 6
  • for multiple data I changed set_user with array tag like this user: [...state,action.payload], but I get error on dispatch(setUser({name:"updatedName",profileId:"updatedId"})) – niphredil Mar 22 '23 at 08:48
  • dispatch(setUser([{name:"updatedName",profileId:"updatedId"}])) and reducer:-[...state.user,action.payload], – Kishan Mar 22 '23 at 13:08
0

You can direct use useSelector value. No need to add useEffect

SecondScreen.js


<code>
 const  user  = useSelector(state => state.user.profileId);

//  useEffect(() => {
    //console.log("Here I wait updated profileId",user.profileId )
  //}, []);//not required useEffect
  console.log("user", user);

</code>
  • OP ***is*** using the `useSelector` hook. The `useEffect` hook usage also isn't in question here. The code you suggest now incorrectly console logs as an unintentional/unexpected side-effect ***because*** it's not using the `useEffect` hook. – Drew Reese Mar 22 '23 at 07:51