当看似未使用的mapStateToProps被移除时,routes.js无法正常工作

时间:2018-05-16 07:53:05

标签: reactjs react-native redux react-redux react-native-router-flux

我现在基本上正在清理我的代码,发现一些奇怪的东西,我发现mapStateToPropsconnect在该文件中的任何地方都没有使用:

import React from 'react';
import { Scene, Router, ActionConst, Stack } from 'react-native-router-flux';
import { connect } from 'react-redux';                  //HERE
import { AsyncStorage } from 'react-native';

//import components for scenes
import Splash from '../components/Splash/Splash';
import Login from '../modules/auth/scenes/Login';
import Home from '../modules/home/scenes/Home';
import itemDescription from '../modules/home/scenes/itemDescription';
import About from '../modules/home/scenes/About';
import Setting from '../modules/home/scenes/Setting';
import NavDrawer from '../modules/home/components/NavDrawer';

//Import Store, actions
import store from '../redux/store'
import * as t from '../modules/auth/actionTypes';

export const mapStateToProps = state => ({                      //HERE
    isLoggedIn: state.authReducer.isLoggedIn 
});

class Routes extends React.Component {
    constructor() {
        super();
        this.state = {
            isReady: false,
            isLoggedIn: false,
            userName:""
        }
    }

    componentDidMount() {
        //load token from async and put it in redux's state
        AsyncStorage.getItem('token').then((data) => {
            setTimeout(() => {
                if (data !== null) {
                    this.setState({ isReady: true, isLoggedIn: true });
                    store.dispatch({ type: t.LOGGED_IN, token: data });
                }
                else {
                    this.setState({ isReady: true, isLoggedIn: false })
                    store.dispatch({ type: t.LOGGED_OUT });
                }
            }, 5000)
        });

        //load username from async storage and put it in route's state to be passed to drawer as props
        AsyncStorage.getItem('username').then(name => {
            this.setState({ userName: name.charAt(0).toUpperCase() + name.slice(1) });
        }); 
    }

    render() {
        if (!this.state.isReady)
            return <Splash />
        return (
            <Router>
                <Scene key="root" hideNavBar>
                    <Stack key="Auth" initial={!this.state.isLoggedIn}>
                        <Scene key="Login" hideNavBar component={Login} title="Login" />
                    </Stack>
                    <Stack key="Main" initial={this.state.isLoggedIn}>
                        <Scene drawer key="NavDrawer" hideNavBar contentComponent={()=><NavDrawer username={this.state.userName}/>} type={ActionConst.REPLACE} panHandlers={null}>
                            <Scene key="homeTab" title="Home" drawerLockMode={'locked-closed'}>
                                <Scene key="Home" hideNavBar component={Home} title={"Home"} />
                                <Scene key="itemDescription" hideNavBar component={itemDescription} title="Item Description" back />
                            </Scene>
                            <Scene key="aboutTab" title="About" drawerLockMode={'locked-closed'}>
                                <Scene key="About" hideNavBar component={About} title={"About"} />
                            </Scene>
                            <Scene key="settingTab" title="Settings" drawerLockMode={'locked-closed'}>
                                <Scene key="Setting" hideNavBar component={Setting} title={"Setting"} />
                            </Scene>
                        </Scene>
                    </Stack>
                </Scene>
            </Router>
        )
    }
}

export default connect(mapStateToProps)(Routes)               //HERE

我很确定这些来自我早期的开发,但我还没有删除,但是,当我尝试删除这3条标记的行,并且只是单独导出默认路由时,发生了一些奇怪的事情:

  1. 登录后键盘不会消失

  2. 依赖于存储在redux状态的令牌的主屏幕数据突然没有获取(获取失败)

  3. 用户名无法加载到抽屉上。

  4. 据我所知mapStateToProps仅用于将redux的状态映射到链接的(使用connect)组件的prop,以便组件可以访问它们。

    它应该是一个只读机制,因为我在store.dispatch

    中使用componentDidMount设置了redux的状态

    对于为什么会发生这种情况,您会猜到什么?我在这里理解错了吗?

    老实说,我不知道在哪里看:(

    提前感谢任何想法!

    更新:我发现上述代码段中的store.dispatch由于某种原因我删除mapStateToProps时没有按时更新令牌,使我的主页无法从其中获取数据componentDidMount()因为令牌仍为空。但是,在Home的生命周期的下一次迭代中,控制台日志显示令牌已更新,但更新后未调用componentDidMount,而是之前。问题仍然存在,为什么mapStateToProps在这种情况下很重要?

1 个答案:

答案 0 :(得分:0)

在整个应用程序中进行一些控制台记录后,我终于知道了mapStateToProps在这种情况下的原因。 所以看起来场景就像这样:

with mapStateToProps:

路线加载令牌 - &gt;发送令牌以存储并开始加载家庭 - &gt; home componentDidMount已触发但令牌仍为null,因为未执行调度 - &gt;一旦完成调度,路由将被重新安装,因为它订阅了使用调度进行更新的mapStateToProp - &gt; home重新加载,这次令牌就在那里

路线加载令牌 - &gt;发送令牌以存储并开始加载家庭 - &gt; home componentDidMount已触发但令牌仍为null,因为未执行调度 - &gt;完成调度后,路由不会重新安装,因为它没有订阅使用调度更新的mapStateToProps - &gt;家没有重新加载

所以看来我的应用程序正在运行,但出于完全错误的原因!!

因此,在我删除mapStateToProps以使我的应用程序在逻辑上合理之后,在我的问题中,它从代码段中的这两个连续行开始:

this.setState({ isReady: true, isLoggedIn: true });
store.dispatch({ type: t.LOGGED_IN, token: data });

这两行在比赛中是 并且序列已经开始关闭,我应该首先dispatched然后将状态设置为isReady:true,这更有意义比上面的片段,因为当我甚至没有将令牌发送到商店时,我怎么能说“嘿,你可以解雇Splash屏幕并开始装回家”!

但即便如此,这两条线仍在竞赛,因为它们都是异步操作,所以现在我唯一的问题是如何解决这个race condition,这更容易理解! :d