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!!!
CodePudding user response:
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])
CodePudding user response:
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());
}, []);