I have the main Stack navigator with multiple screens and one of those screens is a nested Drawer navigator with dynamically created screens.
<Provider store={store}>
<NavigationContainer onStateChange={onStateChange}>
<Stack.Navigator initialRouteName="Launch">
<Stack.Screen name="Launch" component={Launch} />
<Stack.Screen name="Login" component={Login} />
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="ChatBox" component={ChatBox} /> /* <- Here is the drawer navigator screen */
</Stack.Navigator>
</NavigationContainer>
</Provider>
As you can see in the example gif the ChatComponent is always re-rendering when drawer actions were. It does even if the current screen hasn't changed in the drawer's list.
<Drawer.Navigator>
{userChannels.map((channel, index) => {
const chatName = userChannels[index].friendlyName;
const screen = React.memo(() => (
<View style={{ flex: 1 }}>
<Header text={chatName} />
<ChatComponent
channel={channel}
loadEarlier={loadEarlier}
isLoadingEarlier={isLoadingEarlier}
onLoadEarlier={onLoadEarlier}
savedMessages={savedMessages}
onSend={onSend}
isTyping={isTyping}
user={{
_id: me.member.sid || 0,
}}
onInputTextChanged={async () => {
currentChannel &&
(await currentChannel.typing());
}}
enterChannel={() =>
enterChannel(channel.uniqueName)
}
/>
</View>
));
return (
<Drawer.Screen
key={index}
name={chatName || String(index)}
component={screen}
/>
);
})}
</Drawer.Navigator>
The header component is:
export default (props) => {
const { text } = props;
const navigation = useNavigation();
const logout = async () => {
try {
await AsyncStorage.removeItem('accessToken');
await AsyncStorage.removeItem('refreshToken');
} catch (e) {
//
}
navigation.navigate('Login');
};
return (
<View style={styles.header}>
<TouchableOpacity
onPress={() => navigation.dispatch(DrawerActions.openDrawer())}>
<Icon name="menu" color="#FFF" size={18} />
</TouchableOpacity>
{text && <Text style={styles.headerText}>{text}</Text>}
<Text style={styles.headerText} onPress={logout}>
Logout
</Text>
</View>
);
};
The chat component is:
const ChatComponent = React.memo((props) => {
const {
channel,
loadEarlier,
isLoadingEarlier,
onLoadEarlier,
savedMessages,
onSend,
isTyping,
user,
onInputTextChanged,
enterChannel,
} = props;
useEffect(() => {
console.log('render ChatComponent');
enterChannel();
}, []);
return (
<GiftedChat
inverted={false}
loadEarlier={loadEarlier}
isLoadingEarlier={isLoadingEarlier}
onLoadEarlier={onLoadEarlier}
messages={savedMessages}
onSend={onSend}
user={user}
onInputTextChanged={onInputTextChanged}
isTyping={isTyping}
renderBubble={renderBubble}
renderTime={renderTime}
renderInputToolbar={renderInputToolbar}
/>
);
});
Here is the onStateChange of NavigationContainer
How to avoid unnecessary renders of a ChatComponent?