While you have been using useState(), you may wonder if we can share state to other pages. Redux is a JavaScript library for managing state. By using Redux, we can save(dispatch) states into the each local storage(reducer), and retrieve(selector) the state anywhere we want globally. We will talk about dispatch and selector in another chapter.
There are three big steps to set the redux environment :
1. Make reducer in memoSlice.js
2. Make store.js
3. Add provider in App.js
Briefly, reducer is a basket to store global state variables. (step 1) Put each states into slice, and turn the slice into the reducer. You can make multiple reducers by each function or purposes. And then (step 2) you can collect those reducers into store. Once you finish setting up the store, (step 3) use Provider to address store at App.js > app() function.
build a directory "slices" & make "memoSlice.js" in the directory first.
[slices > memoSlice.js]
import { createSlice } from '@reduxjs/toolkit';
const initialState = {
isSignedIn: false,
};
export const memoSlice = createSlice({
name: 'memoState',
initialState,
reducers: {
setIsSignedIn: (state, action) => {
state.isSignedIn = action.payload;
},
}
})
export const {
setIsSignedIn,
} = memoSlice.actions;
// Selectors
export const selectIsSignedIn = (state) => state.memoState.isSignedIn;
export default memoSlice.reducer;
First, we set the initial state of the global state. For us to check if the user is signed in or not, I set the initial state as false for isSignedIn state. Once you set up the initialState, you can use createSlice() and add the variable(issignedIn) to the reducers parameter. Check out the details in redux documentation.
Those setIsSignedIn and selectIsSignedIn are for useDispatch() and useSelector() part. We will handle it more in detail in the another chapter, but those two functions will be used in every screens same as useState() to save & retrieve global states.
You can add more global states if you want.
[store.js]
import { configureStore, combineReducers, getDefaultMiddleware } from "@reduxjs/toolkit";
import memoReducer from './slices/memoSlice';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { persistStore, persistReducer, PERSIST, REGISTER } from 'redux-persist'
const reducers = combineReducers({
signup: memoReducer,
});
const persistConfig = {
key: 'root',
storage: AsyncStorage
};
const persistedReducer = persistReducer(persistConfig, reducers);
export const store = configureStore({
reducer: persistedReducer,
middleware: getDefaultMiddleware({
serializableCheck: {
ignoredActions: [PERSIST, REGISTER],
},
})
});
export const persistor = persistStore(store);
In store.js, we combine existing reducers to a variable "reducers". Separately, we use AsyncStorage to keep the state even if the app has been closed (it is useful to save state data for login status or writing form content). If you wonder more details about the code, please refer to the documentation.
[App.js]
import { NavigationContainer } from '@react-navigation/native';
import { Provider, useDispatch } from 'react-redux';
import { store, persistor } from './store';
import { PersistGate } from 'redux-persist/integration/react';
function AppWrapper() {
const isSignedIn = useSelector(selectIsSignedIn);
return (
<NavigationContainer>
{isSignedIn == true ? (
<MainStack.Navigator>
<MainStack.Screen name="MainMemos" component={MemoStackScreen} />
<MainStack.Screen name="MainUsers" component={UserStackScreen} />
</MainStack.Navigator>
) : (
<LoginStackScreen />
)}
</NavigationContainer>
);
};
export default function App() {
return (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<AppWrapper />
</PersistGate>
</Provider>
);
};
Compared to the previous navigator, we wrap the whole navigation container with AppWrapper() function once more, and use Provider at the App() function. Please keep in mind that we need more import. By wrapping AppWrapper - which is the whole navigator of the app - with Provider, we can use the global states with AsyncStorage to avoid losing state data even after closing the app.
At the next chapter, I will talk about how to save and retrieve global states.