React Native Redux条件LoggedIn渲染会导致竞争条件

时间:2017-06-26 10:38:52

标签: react-native react-redux react-navigation expo

所以我对React Native很新,对redux来说是全新的。我使用条件反应导航渲染创建了一个auth流程,除了给出错误之外,我认为这是由竞争条件引起的。它会检查用户是否已登录并根据它们是否进行渲染而发生的情况。但是如果用户已经登录,它将开始呈现LoginScreen,检测到它们已登录,然后尝试重新呈现,从而导致以下错误:

“警告:setState(...):只能更新已安装或安装的组件。这通常意味着你在未安装的组件上调用了setState()。这是一个无操作。请检查Icon组件的代码。“

我的主要组件如下:

import React, { Component } from "react";
import { StyleSheet, Text, View, AsyncStorage } from "react-native";
import { connect, Provider } from "react-redux";
import Reactotron from "reactotron-react-native";

import { logIn } from "../actions";
import { SignedIn, SignedOut } from "../components/Nav";
import { isSignedIn } from "../components/Auth";
import LoginScreen from "../containers/LoginScreen";

class RootApp extends Component {
    async checkSignedIn() {
        res = await isSignedIn();
        if (res != false) {
            expires = String(res.expires);
            this.props.logIn(res.fbToken, expires);
        } else {
            console.log("Not logged in");
        }
    }

    async componentWillMount() {
        await this.checkSignedIn();
    }

    render() {
        if (this.props.auth.signedIn == true) {
            return <SignedIn />;
        } else {
            return <SignedOut />;
        }
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: "#fff",
        alignItems: "center",
        justifyContent: "center",
        fontSize: 96
    }
});

const mapStateToProps = state => {
    return {
        auth: state.auth
    };
};

const mapDispatchToProps = dispatch => {
    return {
        logIn: fbToken => {
            dispatch(logIn(fbToken, expires));
        }
    };
};

export default connect(mapStateToProps, mapDispatchToProps)(RootApp);

导航看起来像

import React, { Component } from "react";
import { TabNavigator, StackNavigator } from "react-navigation";
import Tasks from "../screens/Tasks";
import Home from "../screens/Home";
import Message from "../screens/Message";
import Profile from "../screens/Profile";
//import WelcomeScreen from "../screens/WelcomeScreen";
import PhoneContacts from "../screens/PhoneContacts";
import { SimpleLineIcons } from "@expo/vector-icons";
import LoginScreen from "../containers/LoginScreen";

const InviteNavigator = StackNavigator({
    DeathMessage: { screen: Message },
    PhoneContacts: { screen: PhoneContacts }
});

export const SignedIn = TabNavigator({
    Tasks: {
        screen: Tasks,
        navigationOptions: {
            tabBarIcon: ({ tintColor }) =>
                <SimpleLineIcons name="list" size={30} />
        }
    },
    Home: {
        screen: Home,
        navigationOptions: {
            tabBarIcon: ({ tintColor }) =>
                <SimpleLineIcons name="home" size={30} />
        }
    },
    Message: {
        screen: InviteNavigator,
        navigationOptions: {
            tabBarIcon: ({ tintColor }) =>
                <SimpleLineIcons name="envelope-letter" size={30} />
        }
    },
    Profile: {
        screen: Profile,
        navigationOptions: {
            tabBarIcon: ({ tintColor }) =>
                <SimpleLineIcons name="user" size={30} />
        }
    }
});

export const SignedOut = StackNavigator({
    SignIn: {
        screen: LoginScreen,
        navigationOptions: {
            title: "Sign In"
        }
    }
});

LoginScreen看起来像:

import { connect } from "react-redux";
import React, { Component } from "react";
import {
    Button,
    View,
    Text,
    ActivityIndicator,
    Alert,
    FlatList
} from "react-native";
import { NavigationActions } from "react-navigation";
import { SocialIcon, Card } from "react-native-elements";
import Reactotron from "reactotron-react-native";
import { AsyncStorage } from "react-native";

import { logIn } from "../actions";
import { signIn } from "../components/Auth";

class SignIn extends Component {
    async handleClick() {
        res = await signIn();
        if (res.type == "success") {
            expires = String(res.expires);
            AsyncStorage.setItem("fbToken", res.token);
            AsyncStorage.setItem("expires", expires);
            this.props.logIn(res.token, expires);
        } else {
            console.log("Login Failed");
        }
    }

    render() {
        return (
            <View style={{ paddingVertical: 20 }}>
                <Card title="finis Requires A Facebook Account To Operate">
                    <SocialIcon
                        title="Fred"
                        button
                        type="facebook"
                        onPress={() => this.handleClick()}
                    />
                </Card>
            </View>
        );
    }
}

const mapDispatchToProps = dispatch => {
    return {
        logIn: fbToken => {
            dispatch(logIn(fbToken, expires));
        }
    };
};

LoginScreen = connect(null, mapDispatchToProps)(SignIn);

export default LoginScreen;

非常感谢任何帮助。如果指向正确的方向,很高兴完全重新设计。

1 个答案:

答案 0 :(得分:0)

通过添加auth.checking道具并渲染活动微调器进行排序,直到它已经检查过。

&#13;
&#13;
    render() {
        if (this.props.auth.checking == true) {
            return (
                <ActivityIndicator
                    animating={true}
                    style={styles.activityIndicator}
                    size="large"
                />
            );
        } else if (this.props.auth.signedIn == true) {
            return <SignedIn />;
        } else {
            return <SignedOut />;
        }
    }
&#13;
&#13;
&#13;