skip to Main Content

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.

3

Answers


  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.

    Login or Signup to reply.
  2. 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

    Login or Signup to reply.
  3. 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>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search