This repo will show you the tips in React Native, this is my experience when I'm working on it. Feel free to create the PR to share your tips!
- Step 1: Create the
RootNavigation.js
file like this
import React from 'react';
export const navigationRef = React.createRef();
export const NavigationAction = navigationRef.current;
export function navigate(name, params) {
navigationRef.current?.navigate?.(name, params);
}
export function goBack() {
if (navigationRef.current?.canGoBack?.()) {
navigationRef.current?.goBack?.();
}
}
- Step 2: Add
navigationRef
to yourNavigationContainer
import { navigationRef } from './routes/RootNavigation';
<NavigationContainer ref={navigationRef}>
<AppContainer />
</NavigationContainer>
- Step 3: Enjoy it
import { navigate, goBack } from './routes/RootNavigation';
navigate('Home', { params });
goBack()
- Step 1: Setup Navigate from anywhere
- Step 2: Update navigate function
import { StackActions } from '@react-navigation/routers';
import isEqual from 'lodash/isEqual';
export function navigate(name, params) {
const pushAction = StackActions.push(name, params);
const { routes = [] } = navigationRef.current?.getRootState?.() || {};
const isExist =
routes.findIndex((item) => {
if (item.name === name && isEqual(item.params, params)) {
return true;
}
return false;
}) >= 0;
if (isExist) {
navigationRef.current?.navigate?.(name, params);
return;
}
navigationRef.current?.dispatch?.(pushAction);
}
Explain: in React Navigation docs navigate
will go back to that screen if it's already in stack, push
will push anyway it's already or not. So we will check if target screen already in stack or not, if it's already and same params we will use navigate for react navigation handle go back, if it's not we will use push
to have same screen but different params.
- Step 3: Enjoy it
- Step 1: Create the
ReduxDispatcher.js
file like this
import React from 'react';
export const dispatchRef = React.createRef();
const ReduxDispatcher = (action) => {
dispatchRef.current?.(action);
};
export default ReduxDispatcher;
- Step 2: Open the file where you had setup the your
Provider
import { store } from './store';
useEffect(() => {
dispatchRef.current = store.dispatch;
return () => {};
}, []);
<Provider store={store}>
// Your App
</Provider>
- Step 3: Enjoy it
import ReduxDispatcher from '@/store/ReduxDispatcher';
ReduxDispatcher(updateUserInfo(params));
When we defined the value in useSelector it didn't check the object as well so we will use shallow compare to make it re-render only when the object had changed.
- Step 1: Create
useShallowEqualSelector
function
import { shallowEqual, useSelector } from 'react-redux';
export function useShallowEqualSelector(selector) {
return useSelector(selector, shallowEqual);
}
- Step 2: Enjoy it
const { uid } = useShallowEqualSelector((state) => ({
uid: state.userInfo?.uid,
}));
❌ Wrong
const { userInfo } = useShallowEqualSelector((state) => ({
userInfo: state.userInfo,
}));
render(){
return <Text>{userInfo.userName}</Text>
}
✅ Correct
const { userName } = useShallowEqualSelector((state) => ({
userName: state.userInfo.userName,
}));
render(){
return <Text>{userName}</Text>
}
Why❓
Because when you defined the object but you only want to use some fields in there it will re-render when you dont want to. Example, you just want to use userName
but you defined the userInfo
object so when userInfo.address
changed your component will re-render.