Reputation: 657
I want to check the Key, if the key exists then I want to set the loggedIn in the initalstate to true. How can I do it? I get no error but my code not working.
import { createSlice } from '@reduxjs/toolkit';
import getSecureKey from '../../../utilies/getSecureKey';
const initialState = {
process: false,
loggedIn: getSecureKey().then(res => res).catch(e => e),
message: '',
error: '',
};
import * as SecureStore from 'expo-secure-store';
const getSecureKey = async () => {
const key = await SecureStore.getItemAsync('jwt');
return key != '' ? true : false
};
export default getSecureKey;
Upvotes: 1
Views: 1575
Reputation: 42208
You cannot use asynchronous code in your initialState
. What this actually does is set your state.loggedIn
property to a Promise
, so you should be getting warnings from redux-toolkit about storing non-serializable values in state.
It takes a moment for the getSecureKey()
function to resolve. But the createStore
/configureStore
function is synchronous and cannot wait for the resolution.
You have two options.
You can wait for getSecureKey()
to resolve before creating the store. Your entire app can't really do anything until the store is created to you would have to render a loading screen instead, similar to what redux-persist does with the PersistGate
component. I don't recommend this.
You can dispatch
an action to update the loggedIn
state after the getSecureKey()
function has finished resolving. You could set the initial value of state.loggedIn
to false
, but I actually recommend using null
or undefined
as a third option which tells you that you don't know yet whether the user is logged in or not. You can use a hook to handle the dispatch
from your top-level App
component. You can use an async thunk as an action creator to automatically handle errors.
Initial state:
const initialState = {
process: false,
loggedIn: null,
message: '',
error: '',
};
Action creator:
export const getInitialKey = createAsyncThunk(
"someActionName",
async () => {
return await getSecureKey();
}
)
In your slice:
extraReducers: {
[getInitialKey.fulfilled]: (state, action) => {
state.loggedIn = action.payload;
},
[getInitialKey.rejected]: (state, action) => {
state.loggedIn = false;
}
}
Auto-dispatch with hook:
const useGetSecureKey = () => {
// we know that a key was received if the state isn't null
const didAttempt = useSelector(state => state.mySlice.loggedIn !== null);
const dispatch = useDispatch();
// dispatches when the state is null
// you could also use an empty dependency array and it's basically the same
useEffect( () => {
if ( ! didAttempt ) {
dispatch(getInitialKey());
}
}, [didAttempt, dispatch]);
}
Upvotes: 1