Drawer's screen component is re-rendering when a drawer opens/closes

502 views Asked by At

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?

0

There are 0 answers