React-native-tab-view: Double render when use Hooks

Created on 21 Apr 2019  路  6Comments  路  Source: satya164/react-native-tab-view


Current behaviour

When use 'switch render' scene inside of the hooks function - I get two renders (when we just start app)

  const _renderScene = ({ route }) => {
    switch (route.key) {
      case 'login':
        return <FirstRoute />;
      case 'sign_up':
        return <SecondRoute />;
      default:
        return null;
    }
  };
index.js:17  FirstRoute
index.js:28 SecondRoute
index.js:17 FirstRoute
index.js:28 SecondRoute



md5-45403528bbdb80af59c5b2a6dd9dd39c



index.js:17 FirstRoute
index.js:28 SecondRoute



md5-600da0461c86973350a711a3ae929354



  const _renderScene = SceneMap({
    login: FirstRoute,
    sign_up: SecondRoute,
  });



md5-4a993263e78a6706010cc6cca3f4d0d1



index.js:17 FirstRoute
index.js:28 SecondRoute



md5-9e83f7f63bafb9900c74e7dbab3c0f21



import React, { useState } from 'react';
import {
  Text,
  View,
  Keyboard,
} from 'react-native';
import EStyleSheet from 'react-native-extended-stylesheet';
import { TabView, TabBar, SceneMap } from 'react-native-tab-view';

import { DEVICE_WIDTH } from 'config/constants';

import styles from './styles';

const FirstRoute = () => {
  console.log('FirstRoute');
  return (
    <View>
      <Text>
        Lorem ipsum dolor sit amet
      </Text>
    </View>
  );
};

const SecondRoute = () => {
  console.log('SecondRoute');
  return (
    <View>
      <Text>
        Lorem ipsum dolor sit amet
      </Text>
    </View>
  );
};

const INITIAL_STATE = {
  index: 0,
  routes: [
    {
      key: 'login',
      title: 'Login',
      icon: '',
      accessibilityLabel: 'Login',
      testID: 'loginTab',
    },
    {
      key: 'sign_up',
      title: 'Register',
      icon: '',
      accessibilityLabel: 'SignIn',
      testID: 'signInTab',
    },
  ],
};

const LoginScreen = () => {
  const [state, setState] = useState(INITIAL_STATE);

  const _renderScene = SceneMap({
    login: FirstRoute,
    sign_up: SecondRoute,
  });

  // const _renderScene = ({ route }) => {
  //   switch (route.key) {
  //     case 'login':
  //       return <FirstRoute />;
  //     case 'sign_up':
  //       return <SecondRoute stings={[]} />;
  //     default:
  //       return null;
  //   }
  // };

  const _handleIndexChange = (index) => {
    Keyboard.dismiss();
    setState({ ...INITIAL_STATE, index });
  };

  const _renderTabBar = props => (
    <TabBar
      {...props}
      activeColor={EStyleSheet.value('$primaryColor')}
      inactiveColor="black"
      style={styles.tabBar}
      indicatorStyle={styles.indicatorStyle}
    />
  );

  return (
    <View style={styles.container}>
      <TabView
        // lazy
        navigationState={state}
        renderScene={_renderScene}
        renderTabBar={_renderTabBar}
        onIndexChange={_handleIndexChange}
        // swipeEnabled={false}
        initialLayout={{
          height: 0,
          width: DEVICE_WIDTH,
        }}
      />
    </View>
  );
};

export default LoginScreen;

Your Environment

| software | version
| ---------------------------- | -------
| ios or android | both
| react-native | 0.59.4
| react-native-tab-view | ^2.2.0
| react-native-gesture-handler | kmagiera/react-native-gesture-handler#ff74e0e
| react-native-reanimated | ^1.0.1
| node | v10.15.3
| npm or yarn | yarn

All 6 comments

I encountered this recently. The problem is that your scenes are re-created every time the Login screen re-rendered.
You should wrap the scene map creating function in a useCallback hook like this:

const _renderScene = useCallback(SceneMap({
    login: FirstRoute,
    sign_up: SecondRoute
}));

Yep, thx
i have solved this also with
const firstRoute = useMemo(() => (<LoginUser />), []);
or
const LoginUser = React.memo(() => (<LoginUser />));

Closing since this seems to be resolved.

Hm, I think it is still an issue, I have tried @Akyna and @tranhoangduong1994 solutions, but the useEffect hook inside on scene components gets called 3 times.

The library doesn't treat function components or hooks in a special way. So if there is different behaviour in your component, there's likely some error in your code. If you believe it's actually a bug in the library, please open an issue with a runnable repro.

@satya164 you are right

Was this page helpful?
0 / 5 - 0 ratings