Closed cglacet closed 1 year ago
Couldn't find version numbers for the following packages in the issue:
react-native
Can you update the issue to include version numbers for those packages? The version numbers must match the format 1.2.3.
The versions mentioned in the issue for the following packages differ from the latest versions on npm:
react-native-tab-view
(found: 3.0.0
, latest: 3.2.1
)react-native-pager-view
(found: 4.2.4
, latest: 6.0.1
)expo
(found: 46.0.0
, latest: 46.0.14
)Can you verify that the issue still exists after upgrading to the latest versions of these packages?
Couldn't find version numbers for the following packages in the issue:
react-native
Can you update the issue to include version numbers for those packages? The version numbers must match the format 1.2.3.
The versions mentioned in the issue for the following packages differ from the latest versions on npm:
expo
(found: 46.0.0
, latest: 46.0.14
)Can you verify that the issue still exists after upgrading to the latest versions of these packages?
I also tried replacing the renderScene
by a simple function, but this leads to the same bug:
const renderScene = React.useCallback(({route}: {route: RouteParams}) =>
<Route {...route}/>, []
);
The bug also appears with static routes, the following also triggers useless re-renders even though the code uses constants in the Nav
component.
const renderScene = SceneMap({0: Route, 1: Route});
const routes = routesParams(2);
function Nav({nbTabs}:{nbTabs: number}){
const [index, setIndex] = React.useState(0);
return <TabView
navigationState={{ index, routes }}
renderScene={renderScene}
onIndexChange={setIndex}
/>
}
If there's a bug with SceneMap
or React.memo
/React.PureComponent
please open a separate issue with repro. Creating components in render/useMemo
/useCallback
aren't for memoing a component.
Yes there is a bug with SceneMap
. Render functions passed into it are called multiple times. I provided a reproduction here.
SceneMap
doesn't accept render functions. It accepts React components which should be defined outside of other components.
Then the documentation is out of date as it clearly states that SceneMap
excpect an objetct with key to function maping.
const FirstRoute = () => (...);
const renderScene = SceneMap({
first: FirstRoute,
});
That's a component defined outside of a component, not a regular function. Documentation also explicitly says not to pass a inline function: https://github.com/satya164/react-native-tab-view#renderscene-required
Changing the code to:
const renderScene = SceneMap(
Object.fromEntries(
routes.map((c) => [
c.key,
Route,
])
)
);
Doesn't make any difference. The problem is that render functions are called even when the input props (route params for exemple) are untouched.
please open a new issue with a minimal repro that uses only SceneMap
/React.memo
if it's not working properly
Why a new one? This one shows exactly how it's not working properly.
I think I found the issue in the code, here there is something like:
return (
<>
{
navigationState.routes.map((route, i) => {
renderScene(route);
})
};
</>
);
But it should be something like:
const scenes = useMemo(() => {
navigationState.routes.map((route, i) => {
renderScene(route);
});
}, [navigationState.routes]);
return <>{scenes}</>;
This one has incorrect snack and incorrect code in the description. It's better to create a new issue with proper code and repro so the person looking into it doesn't need to read the whole discussion.
What do you mean "incorrect snack"? The snack shows an example where route props are not managed properly even when using SceneMap
.
But it should be something like:
Memoizing components doesn't work that way. This is also unsafe and will prevent re-renders even if renderScene
refers to a variable in the closure. If renderScene
is used inside useMemo
then it should be in dependency array to be used safely.
What do you mean "incorrect snack"
As I said, you cannot create components inside other components which is what your snack does and the documentation explicitly says not to do. Please create a minimal repro following the docs if there is a bug.
Current behavior
The following code will render each tab two times on init and one time on every tab change.
We can add some logs to check the code on our side is doing what we excpect. For example we can add a log within the routes
useMemo
, and indeed it's only called once (during init) :The changed part of the code:
Even if the docs says
SceneMap
acts as a memoizer for routes, I also checked this wasn't the issue (encapsulating it inuseMemo
). This doesn't change anythin.Expected behavior
All routes should render exactly once.
Reproduction
https://snack.expo.dev/jKHFsGJ94
Platform
Environment
The environement is the one linked in the documentation: