Screens within a stack or in tabs will still render when any global state(Redux/Context etc) is updated. This component lets you avoid these renders when the screens are inactive.
Read a more in depth article about this here
npm i react-navigation-focus-render --save
import FocusRender from 'react-navigation-focus-render'
const ExpensiveComponent = () => {
const {count} = useCount(); // something that hooks into changing state
return (
<FocusRender>
... Components that will only re-render when the screen is focused
</FocusRender>
)
}
You may wish to add a wrapper component that displays differently whilst the inactive component hydrates its state when the screen becomes active.
You can specify a Wrapper component that takes isFocused as a property.
import FocusRender from 'react-navigation-focus-render'
const Wrapper = ({isFocused, children}) => (
<View style={{opacity: isFocused ? 1 : 0.5}}>{children}</View>
);
const ExpensiveComponent = () => {
const {count} = useCount(); // something that hooks into changing state
return (
<FocusRender Wrapper={Wrapper}>
... Components that will only re-render when the screen is focused
</FocusRender>
)
}
This repository includes an example project that demonstrates this working in a simple way.
- Contains an expensive component that renders 5000 text elements and is connected to redux state "count"
- You can toggle between rendering the component via FocusRender or just by itself
- Contains a screen with a button that updates state "count"
Given this simple example, the difference in performance when updating state can be measured using https://github.com/Flagsmith/react-native-performance-monitor.
Of course, this is quite an extreme example but given an active stack of many tabs / screens this could easily add up if you have complex components.