aksonov / react-native-tabs

React Native platform-independent tabs. Could be used for bottom tab bars as well as sectioned views (with tab buttons)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

With router-flux: Tab re-renders one more time

dswbx opened this issue · comments

commented

Using:
react-native-router-flux@3.36.0
react-native-tabs@1.0.9
react-native@0.35.0
react@15.3.2

Demo

Description:

  1. start app, renders tab "Feed" initially
  2. switch to "Tab #2" and then back to "Feed" - this re-renders tab "Feed"
  3. switching to second and back to initial tab does not re-render tab "Feed" again

I expect tabs to not re-render, but I think this is caused by tab 2 being rendered after clicked (and forces tab 1 to re-render as well). Is there an option to automatically render all tabs at start? Or is this behavior caused by something else? I've attached all that might be helpful, sorry if this post is very long.

Scenes:

//...
class AppNavigator extends React.Component
{
    render()
    {
        return <RouterWithRedux>
            <Scene key="root" style={{backgroundColor: 'yellow'}}>
                <Scene open={false} component={Drawer} key="drawer" sceneStyle={[AppStyle.sceneTab, {borderWidth: 1, borderColor: 'red'}]}>
                    <Scene key="main" tabs initial={true} tabBarStyle={{backgroundColor: 'rgba(0,0,0,.4)', borderWidth: 1, borderColor: 'blue'}}>
                        <Scene key="main_back" onPress={() => Actions.pop()} title="Back" icon={TabIcon} />

                        <Scene key="Page1" title="Feed" icon={TabIcon} initial={true} sceneStyle={{borderWidth: 1, borderColor: 'green'}}>
                            <Scene key="Feed" component={Scenes.Page1} hideNavBar={true} initial={true} sceneStyle={{borderWidth: 1, borderColor: 'yellow', backgroundColor: 'yellow'}} />
                            <Scene key="detail" component={Scenes.Page3} hideNavBar={true} title="PostDetail" />
                        </Scene>

                        <Scene key="Page2" component={Scenes.Page2} hideNavBar={true} title="Tab #2" icon={TabIcon} />
                        <Scene key="open_drawer" title="Drawer" icon={TabIcon} onPress={() => Actions.refresh({key: 'drawer', open: value => !value })} />
                    </Scene>

                    <Scene key="auth" type={ActionConst.REPLACE}>
                        <Scene key="Login" component={Scenes.Login} title="Login" initial={true} />
                        <Scene key="Register" component={Scenes.Register} title="Register" />
                    </Scene>
                </Scene>
            </Scene>
        </RouterWithRedux>
    }
}

function mapDispatchToProps(dispatch)
{
    return bindActionCreators(ActionCreators, dispatch);
}

export default connect((state) => {
    return {}
}, mapDispatchToProps)(AppNavigator);

Page1.js (Feed tab):

//...
class Page1 extends Component
{
    _addRecipe()
    {
        this.props.addRecipe();
    }

    componentDidMount()
    {
        this.props.fetchPosts();
    }

    render()
    {
        console.log('page1props', this.props);

        return <AnimatableScrollView
            animation="fadeIn"
            contentContainerStyle={[ ScrollViewStyle.contentContainerStyle ]}
            style={[ AppStyle.sceneTabInner, ScrollViewStyle.style ]}
        >
            <Animatable.Text animation="zoomIn" style={{color: 'white'}} onPress={Actions.Page2}>
                Page1
            </Animatable.Text>
            <Text onPress={() => this._addRecipe()}>Add recipe</Text>
            <Text>Recipe count: {this.props.recipeCount}</Text>
            <Text style={{marginTop:40}} onPress={() => Actions.auth()}>Goto login</Text>
            {this.props.posts.length > 0 && this.props.posts.map((value, key) => {
                postAnimationDelay += postAnimationIteration;

                return <Animatable.View animation="fadeInUp" delay={postAnimationDelay} duration={300} key={value.id} style={{marginTop: 20}}>
                    <TouchableOpacity onPress={() => Actions.detail({
                        post: value
                    })}>
                        <Text>{value.title}</Text>
                    </TouchableOpacity>
                </Animatable.View>
            })}
            <Text onPress={() => Actions.detail()} style={{marginTop:40}}>asdf</Text>
        </AnimatableScrollView>
    }
}


export default connect((state) => { // state == global state
    return {
        routes: state.routes,
        searchedRecipes: state.searchedRecipes,
        recipeCount: state.recipeCount,
        posts: state.posts
    }
}, (dispatch) => bindActionCreators(ActionCreators, dispatch))(Page1);

Page2.js (Tab #2):

//...
class Page2 extends Component
{
    _removeRecipe()  { this.props.removeRecipe();  }

    render()
    {
        return <View style={{flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: 'red'}}>
            <Text style={{color: 'white'}} onPress={Actions.pop}>
                Page2
            </Text>
            <Text onPress={() => this._removeRecipe()}>Remove recipe</Text>
            <Text>Recipe count: {this.props.recipeCount}</Text>
            <Text style={{marginTop:40}} onPress={() => Actions.auth()}>Goto login</Text>
        </View>
    }
}

export default connect((state) => { // state == global state
    return {
        routes: state.routes,
        searchedRecipes: state.searchedRecipes,
        recipeCount: state.recipeCount
    }
}, (dispatch) => bindActionCreators(ActionCreators, dispatch))(Page2);

Console ouput of Demo GIF:

Running application App ({
    initialProps =     {
    };
    rootTag = 1;
})
Running application "App" with appParams: {"rootTag":1,"initialProps":{}}. __DEV__ === true, development-level warning are ON, performance optimizations are OFF
fetching url https://...
 action @ 13:06:08.324 REACT_NATIVE_ROUTER_FLUX_FOCUS 
 prev state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[0]}
 action Object {scene: Object, type: "REACT_NATIVE_ROUTER_FLUX_FOCUS"}
 next state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[0]}
 action @ 13:06:08.336 REACT_NATIVE_ROUTER_FLUX_FOCUS 
 prev state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[0]}
 action Object {scene: Object, type: "REACT_NATIVE_ROUTER_FLUX_FOCUS"}
 next state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[0]}
 action @ 13:06:08.749 REACT_NATIVE_ROUTER_FLUX_REFRESH 
 prev state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[0]}
 action Object {key: "0_drawer", open: false, type: "REACT_NATIVE_ROUTER_FLUX_REFRESH"}
 next state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[0]}
 action @ 13:06:08.753 REACT_NATIVE_ROUTER_FLUX_FOCUS 
 prev state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[0]}
 action Object {scene: Object, type: "REACT_NATIVE_ROUTER_FLUX_FOCUS"}
 next state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[0]}
response Object {limit: 10, offset: 0, data: Array[10], single_result: false}
 action @ 13:06:09.151 SET_POSTS 
 prev state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[0]}
 action Object {type: "SET_POSTS", posts: Array[10]}
 next state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}
 action @ 13:06:38.433 REACT_NATIVE_ROUTER_FLUX_JUMP 
 prev state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}
 action Object {key: "Page2", type: "REACT_NATIVE_ROUTER_FLUX_JUMP"}
 next state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}
 action @ 13:06:38.438 REACT_NATIVE_ROUTER_FLUX_FOCUS 
 prev state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}
 action Object {scene: Object, type: "REACT_NATIVE_ROUTER_FLUX_FOCUS"}
 next state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}
 action @ 13:06:38.469 REACT_NATIVE_ROUTER_FLUX_FOCUS 
 prev state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}
 action Object {scene: Object, type: "REACT_NATIVE_ROUTER_FLUX_FOCUS"}
 next state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}
 action @ 13:06:40.121 REACT_NATIVE_ROUTER_FLUX_JUMP 
 prev state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}
 action Object {key: "Page1", type: "REACT_NATIVE_ROUTER_FLUX_JUMP"}
 next state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}
 action @ 13:06:40.125 REACT_NATIVE_ROUTER_FLUX_FOCUS 
 prev state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}
 action Object {scene: Object, type: "REACT_NATIVE_ROUTER_FLUX_FOCUS"}
 next state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}
 action @ 13:06:40.137 REACT_NATIVE_ROUTER_FLUX_FOCUS 
 prev state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}
 action Object {scene: Object, type: "REACT_NATIVE_ROUTER_FLUX_FOCUS"}
 next state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}
fetching url https://...
response Object {limit: 10, offset: 0, data: Array[10], single_result: false}
 action @ 13:06:41.602 SET_POSTS 
 prev state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}
 action Object {type: "SET_POSTS", posts: Array[10]}
 next state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}
 action @ 13:06:50.044 REACT_NATIVE_ROUTER_FLUX_JUMP 
 prev state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}
 action Object {key: "Page2", type: "REACT_NATIVE_ROUTER_FLUX_JUMP"}
 next state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}
 action @ 13:06:50.048 REACT_NATIVE_ROUTER_FLUX_FOCUS 
 prev state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}
 action Object {scene: Object, type: "REACT_NATIVE_ROUTER_FLUX_FOCUS"}
 next state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}
 action @ 13:06:50.062 REACT_NATIVE_ROUTER_FLUX_FOCUS 
 prev state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}
 action Object {scene: Object, type: "REACT_NATIVE_ROUTER_FLUX_FOCUS"}
 next state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}
 action @ 13:06:50.919 REACT_NATIVE_ROUTER_FLUX_JUMP 
 prev state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}
 action Object {key: "Page1", type: "REACT_NATIVE_ROUTER_FLUX_JUMP"}
 next state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}
 action @ 13:06:50.926 REACT_NATIVE_ROUTER_FLUX_FOCUS 
 prev state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}
 action Object {scene: Object, type: "REACT_NATIVE_ROUTER_FLUX_FOCUS"}
 next state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}
 action @ 13:06:50.947 REACT_NATIVE_ROUTER_FLUX_FOCUS 
 prev state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}
 action Object {scene: Object, type: "REACT_NATIVE_ROUTER_FLUX_FOCUS"}
 next state Object {searchedRecipes: Object, recipeCount: 17, routes: Object, posts: Array[27261]}

I'm experiencing exactly the same issue using tabs with react-native-router-flux (I think it uses react-native-tabs): aksonov/react-native-router-flux#1669

Did you found any solution?

I am having the same problem. It was working fine few days back!

Anyone found a solution for this?

commented

This may happen because tab contents gets unmounted when another tab pressed, therefore needs to rerender... It's something I can't accept, think about scroll position that is getting lost when tab changes. I ended up using this:

https://github.com/skv-headless/react-native-scrollable-tab-view
Tabs stays along with each other, so they won't be rerendered. You could also disable swipe and transition so it feels exactly like tabs. Hope this helps you guys as much as it helped me.

@rssfeed I think the problem was with the version of the module. It somehow breaks after version 3.37.0
I rolled back to version 3.37.0 and now it is working fine like before.

@rssfeed How to navigate multiple scenes within a tab in react native scrollable tab view?