skip to Main Content

Hello guys, sorry for my English it’s my second language.
So i have a Redux state which looks something like this:

const initialState = {
  user: null,
  isLoading: false,
};

And each time i load main screen(I’m using React Native), i take a user from local storage and put it in the state:

useEffect(() => {
    dispatch(getMe());
    dispatch(getCategories());
  }, []);

With a getMe function i take a user from local storage and with a getCategories one i make request to the api and get data. But if i would take a state value when getting categories, i get a null(default value):

// Get categories
export const getCategories = createAsyncThunk(
  "categories/get",
  async (_, thunkAPI) => {
    try {
      console.log(thunkAPI.getState().user.user);
      // The thunkAPI.getState().user.user value is null
      return await categoryService.getCategories();
    } catch (error) {
      thunkAPI.rejectWithValue(error);
    }
  }
);

I was just interested what would happen if i timeout getCategories function:

useEffect(() => {
    dispatch(getMe());
    setTimeout(() => dispatch(getCategories()), 1);
  }, []);

And it works. But i don’t really think it’s a good way to do that, So how do i fix this "properly"?

Previously thanks!!!

2

Answers


  1. You are not getting the updated value in async function because in react, updating state is asynchronous. You can get the updated state after react renders that component.

    You can have two useEffects.
    In first useEffect, dispatch getMe function. This useEffect will run once.
    Then get the user value from store.
    Then in second useEffect, pass that state in dependency array. Now add a condition to check if user is not null, then dispatch getCategories function.

    // Get The User Value From Store
    const user = useSelector((state) => ...);
    
    useEffect(() => {
        dispatch(getMe())
    }, [])
    
    useEffect(() => {
        if (user) { 
            dispatch(getCategories())
        }
    }, [user])
    
    Login or Signup to reply.
  2. Just wait for getMe to be resolved before calling getCategories. No one guarantees you that getCategories will be resolved in n ms.

    useEffect(() => {
        const getData = async () => {
          await dispatch(getMe()); // wait for the promise to resolve
          dispatch(getCategories());
        }
        getData();
      }, []);
    

    Or you could also call getMe in your getCategories thunk:

    export const getCategories = createAsyncThunk(
      "categories/get",
      async (_, thunkAPI) => {
        try {
          await thunkAPI.dispatch(getMe()); // wait for the promise to resolve
          console.log(thunkAPI.getState().user.user);
          // The thunkAPI.getState().user.user value is null
          return await categoryService.getCategories();
        } catch (error) {
          thunkAPI.rejectWithValue(error);
        }
      }
    );
    

    and just call getCategories in your component

    // your component
    useEffect(() => {
      dispatch(getCategories());
    }, []);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search