React-native-tab-view: Refresh component after tab press

Created on 8 Feb 2019  路  13Comments  路  Source: satya164/react-native-tab-view


Current behaviour

all views are loaded when I click on the navigation button that shows me the tab view, i use redux

Expected behaviour

the view should be reloaded with each click on a different tab

Code sample

constructor(props) {
    super(props);

    this.state = {
        index: 0,
        routes: [
            {key: 'first', icon: 'backup-restore', title: 'Suggestions'},
            {key: 'second', icon: 'heart',title: 'Favoris'},
            {key: 'third', icon: 'package',title: 'Tous les produits'},
        ],
    };
}

_renderIcon = ({ route }) => {
    const color = (this.state.currentRoute === route.key) ? '#74B9FF' : '#C3CEE2';
    return <Icon name={route.icon} type="material-community" size={16} color={color} />
}

_renderTabBar = props => (
    <TabBar
        {...props}
        scrollEnabled
        renderIcon={this._renderIcon}
        renderLabel={this._renderLabel}
        indicatorStyle={styles.indicator}
        style={styles.tabbar}
        tabStyle={styles.tab}
    />
);

_renderLabel = ({route}) => {
    const label = route.title
    return <Text style={[ styles.label, {color: this.state.currentRoute === route.key ? '#74B9FF' : '#C3CEE2'}]}>{label}</Text>
}

_handleIndexChange = index => {
    const currentRoute = this.state.routes[index].key;
    this.setState({
        index, currentRoute
    });
}

_renderScene = ({ route }) => {
    switch (route.key) {
        case 'first':
            return <InfiniteListContainer endpoint="/buyer/suggested-items" card={ProductCardContainer}/>;
        case 'second':
            return <InfiniteListContainer endpoint="/buyer/item-favorites" card={ProductCardContainer}/>;
        case 'third':
            return <InfiniteListContainer endpoint="/buyer/suppliers" card={SupplierCardContainer}/>;
        default:
            return null;
    }
};

render () {
    return (
        <View style={{flex: 1, backgroundColor: '#F4F7F9'}}>
            <View style={{alignItems: 'center', marginBottom: 20}}>
                <View style={{ flexDirection: 'row', alignItems: 'center', marginTop: 20}}>
                    <Icon name="cart" type="material-community" size={25}/>
                    <Text>Passer une commande</Text>
                </View>
                <View style={{marginTop: 20}}>
                    <Text style={dashBoardStyles.lightTextTopColor}>S茅lectionnez la quantit茅 souhait茅e pour mettre 脿 joour le panier</Text>
                </View>
            </View>

            <TabView
                navigationState={this.state}
                renderScene={this._renderScene}
                renderTabBar={this._renderTabBar}
                onIndexChange={this._handleIndexChange}
            />

        </View>
    )
}

Screenshots (if applicable)

What have you tried

all issues, componentDidUpdate, componentWillReceiveProps, componentWillUpdate

Your Environment

| software | version
| --------------------- | -------
| ios or android | android
| react-native | 0.57.8
| react-native-tab-view | last version
| node | v11.6.0
| npm or yarn | yarn

Most helpful comment

@tmjordan Here is mine

<TabView
    navigationState={this.state}
    renderScene={({ route }) => {      <-------- 
        switch (route.key) {
        case 'first':
            return this.firstRoute();
        case 'second':
            return this.secondRoute();
        default:
            return null;
        }
    }}
    onIndexChange={index => {
        this.setState({
            index: index
        })
    }}
    initialLayout={{ 
        width: Dimensions.get('window').width ,
        height: Dimensions.get('window').height
    }}
    renderTabBar={this.renderTabBar}
/>

All 13 comments

i have a same problem, i can't use setstate to rerender components when using tabview.
Nothing happens

I fix this by using renderScene directly instead of using SceneMap.

All the scenes rendered with SceneMap are optimized using React.PureComponent and don't re-render when parent's props or states change. If you don't want this behaviour, or want to pass additional props to your scene components, use renderScene directly instead of using SceneMap.

Hi @inkwaris , thanks for your help.
Please how do you use renderScene directly instead of using SceneMap. Here is what i did:
<TabView renderTabBar={props => <TabBar {...props} style={{ backgroundColor: RkTheme.current.colors.screen.base }} indicatorStyle={{ backgroundColor: RkTheme.current.colors.text.accent }} labelStyle={{color: RkTheme.current.colors.text.accent}} /> } navigationState={this.state} renderScene={SceneMap({ first: this.FirstRoute, second: SecondRoute, })} onIndexChange={index => this.setState({ index })} initialLayout={{ height: 0, width: Dimensions.get('window').width }} />

renderScene={
SceneMap({
first: FirstRoute,
second: SecondRoute,
})
}

@tmjordan Here is mine

<TabView
    navigationState={this.state}
    renderScene={({ route }) => {      <-------- 
        switch (route.key) {
        case 'first':
            return this.firstRoute();
        case 'second':
            return this.secondRoute();
        default:
            return null;
        }
    }}
    onIndexChange={index => {
        this.setState({
            index: index
        })
    }}
    initialLayout={{ 
        width: Dimensions.get('window').width ,
        height: Dimensions.get('window').height
    }}
    renderTabBar={this.renderTabBar}
/>

@inkwaris I tried your solution still nothing

Thank You very much @inkwaris , it's working now :)

@HakanAkca try using to implement the redenScene function directly in the Tabview component, as shown in @inkwaris 's example. It works for me, that way

just use his example entirely, before updating

@tmjordan can you past your full code here please if possible ?

@HakanAkca

state = {
    index: 0,
    routes: [
        { key: 'first', title: 'First' },
        { key: 'second', title: 'Second' },
    ],
    show: false,
};

FirstRoute = () => (
    <View style={[styles.scene, { backgroundColor: 'orange' }]} />
);

SecondRoute = () => (
    <View style={[styles.scene, { backgroundColor: '#673ab7' }]} />
);

_handleIndexChange = index => {
    this.setState({
        index: index
    })
};

_renderTabBar = props => (
    <TabBar
        {...props}
        style={{ backgroundColor: RkTheme.current.colors.screen.base }}
        indicatorStyle={{ backgroundColor: RkTheme.current.colors.text.accent }}
        labelStyle={{color: RkTheme.current.colors.text.accent}}
    />
);

render() {
    return (
        <TabView
            navigationState={this.state}
            renderTabBar={this._renderTabBar}
            renderScene={({ route }) => {
                switch (route.key) {
                    case 'first':
                        return this.FirstRoute();
                    case 'second':
                        return this.SecondRoute();
                    default:
                        return null;
                }
            }}
            onIndexChange={this._handleIndexChange}
            initialLayout={{
                width: Dimensions.get('window').width,
                height: Dimensions.get('window').height
            }}
        />
    )
}

Hey, I just released a new alpha 2.0.0-alpha.0 of the library. It's rewritten using react-native-gesture-handler and react-native-reanimated addresses a many platform specific bugs and performance problems. The documentation is updated as well.

Please try the new version and see if it addresses your issue. If not, please open a new issue following the issue template.

I have answered, how to change data on any tab from other tab.
https://stackoverflow.com/a/61033933/11392122

Was this page helpful?
0 / 5 - 0 ratings

Related issues

karthikeyansundaram2 picture karthikeyansundaram2  路  3Comments

t3chnoboy picture t3chnoboy  路  3Comments

AndriiUhryn picture AndriiUhryn  路  3Comments

compojoom picture compojoom  路  4Comments

ios-dev-newbie picture ios-dev-newbie  路  3Comments