I'm trying to understand the reasoning behind the following behavior. Is this a bug or intended behavior?
As an example, there are two tabs total -
When moving between tabs with the tab bar, renderScene is called once per tab, 2 times total. I don't quite get why it happens at all? It was already called before, so why it is needed to be called again?
When moving between tabs with a gesture, renderScene is called twice per tab. Tab A, then Tab B, then Tab A again, then Tab B.
renderScene should not be called for every tab change, but it certainly shouldn't be called twice per tab change with a gesture.
The components that are returned from renderScene are using React.memo and are not actually being rendered, so this is not actually expensive. I'm just trying to understand the reasoning behind this behavior and if it's a bug.
| software | version
| ---------------------------- | -------
| ios or android | ios
| react-native | 0.61.4
| react-native-tab-view | 2.11.0
| react-native-gesture-handler | 1.5.2
| react-native-reanimated | 1.4.0
| node | 12.13.1
| npm or yarn | npm
same problem ,
same problem ,
i solved this problem just now.maybe this way can help
renderScene={SceneMap(this.renderScenes)}
this prop should be a const parameter,'this.renderScenes' should be const
this.renderScenes = this.renderScenes();
this way had solved my problem..by the way dont put the renderScenes in render method
@shadow-boy what does renderScenes look like? What's the return value?
I'm trying to understand the reasoning behind the following behavior. Is this a bug or intended behavior?
As an example, there are two tabs total -
When moving between tabs with the tab bar, renderScene is called once per tab, 2 times total. I don't quite get why it happens at all? It was already called before, so why it is needed to be called again?
Imagine this code:
function MyComponent() {
const items = ['a', 'b'];
return (
<View>
{items.map(item => {
console.log('called');
return <Text>{item}</Text>;
)}
</View>
);
}
Whenever this component re-renders, your console.log will be called multiple times (twice here with the 2 items). Your screens aren't any different. Every render, we need to re-render children as well, otherwise things will be out of date (e.g. if you're using parent state inside renderScene and the state changes). It's called 2 times per update because you have 2 items, like the map here. If we internally update state in the library, it'll cause a re-render.
This is not a bug. This is how React works. The docs specifically tell you this https://github.com/react-native-community/react-native-tab-view#avoid-unnecessary-re-renders
@satya164: When moving between tabs with a gesture, renderScene is called twice per tab. Why is that?
Why does it matter?
@satya164 I memoized my tab components, so it doesn't, but I still wonder why does it call renderScene twice per tab. seems wasteful?
@satya164 does this mean if I'm using functional component with react-native-tab-view, then it's inevitable to get every scene rerendered whenever I switch a tab?
the code pattern is like this:
const Component = (props) => {
const [index, setIndex] = useState(0)
const [routes] = React.useState([
{ key: 'first', title: 'First' },
{ key: 'second', title: 'Second' },
]);
const renderScene = ({ route }) => {
const data = datas[route.key]
return <AnotherComponent data={data} >
}
return (
<TabView
navigationState={{ index, routes }}
renderScene={renderScene}
onIndexChange={setIndex}
initialLayout={initialLayout}
/>
);
}