使用 React Navigation 和 Redux React Native Auth

React Native Auth with React Navigation and Redux

我刚刚开始将 Redux 集成到我的第一个 React Native (Expo.io) 项目中。我的登录与 Redux 配合得很好,但是当我尝试在我的应用程序的其中一个屏幕上创建注销按钮时,它实际上会在加载它时立即触发注销调度。我想我一定是误解了 Redux 连接和 mapDispatchToProps 的工作方式。我已经多次阅读文档,但仍然卡住了。这是非工作状态下的代码。

登录 - 一直有效,直到我在配置文件页面上添加注销调度

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 { logIn } from "../actions";
import { signIn } from "../components/Auth";

class SignIn extends Component {
    async handleClick() {
        res = await signIn();
        if (res != false) {
            this.props.logIn(res.token);
        } 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));
        }
    };
};

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

export default LoginScreen;

减速机

import { combineReducers } from "redux";
import Reactotron from "reactotron-react-native";

import { LOG_IN, LOG_OUT, ADD_PHONE_CONTACTS } from "../actions/actions";

const initialState = {
    signedIn: false,
    fbToken: "fred",
    test: undefined,
    phoneContacts: {}
};

const finis = combineReducers({
    auth,
    phoneContacts
});

function auth(state = initialState, action) {
    switch (action.type) {
        case LOG_IN:
            Reactotron.log("LOG IN");
            return {
                ...state,
                signedIn: true,
                fbToken: action.fbToken
            };
        case LOG_OUT:
            Reactotron.log("LOG OUT");
            return {
                ...state,
                signedIn: false,
                fbToken: undefined
            };

        default:
            return state;
    }
}

function phoneContacts(state = [], action) {
    switch (action.type) {
        case ADD_PHONE_CONTACTS:
            console.log("Adding Contacts");
            return {
                ...state,
                phoneContacts: action.phoneContacts
            };
        default:
            return state;
    }
}

export default finis;

配置文件 无效。在不按下按钮的情况下触发 LOG_OUT 操作。

import React, { Component } from "react";
import { Button, Card } from "react-native-elements";
import { View, Text, ActivityIndicator, AsyncStorage } from "react-native";
import { MapView } from "expo";
import { connect } from "react-redux";
import { bindActionCreators } from "redux";
import { SimpleLineIcons } from "@expo/vector-icons";
import Reactotron from "reactotron-react-native";

import * as ActionCreators from "../actions";
import { signOut } from "../components/Auth";

class ProfileWrap extends Component {
    handleClick() {
        Reactotron.log(this.Actions);
        this.props.logOut();
    }

    render() {
        return (
            <View style={{ paddingVertical: 20 }}>
                <Card title="Profile">
                    <View
                        style={{
                            backgroundColor: "#bcbec1",
                            alignItems: "center",
                            justifyContent: "center",
                            width: 80,
                            height: 80,
                            borderRadius: 40,
                            alignSelf: "center",
                            marginBottom: 20
                        }}
                    >
                        <Text style={{ color: "white", fontSize: 28 }}>JD</Text>
                    </View>
                    <Button title="Log Out" onPress={this.handleClick} />
                </Card>
            </View>
        );
    }
}

mapDispatchToProps = dispatch => {
    return { 
        logOut: dispatch(logOut())
    };
};

const Profile = connect(null, mapDispatchToProps)(ProfileWrap);

export default Profile;

任何帮助将不胜感激,即使它告诉我我做错了整件事 :) 已经花了几个小时了。

NEW Profile.js - 无法读取 属性 'logOut' of undefined

import React, { Component } from "react";
import { Button, Card } from "react-native-elements";
import { View, Text, ActivityIndicator, AsyncStorage } from "react-native";
import { MapView } from "expo";
import { connect } from "react-redux";
import { SimpleLineIcons } from "@expo/vector-icons";

import { logOut } from "../actions";
import { signOut } from "../components/Auth";

class ProfileWrap extends Component {
    handleClick() {
        console.log(this.props);
        this.props.logOut();
    }

    render() {
        return (
            <View style={{ paddingVertical: 20 }}>
                <Card title="Profile">
                    <View
                        style={{
                            backgroundColor: "#bcbec1",
                            alignItems: "center",
                            justifyContent: "center",
                            width: 80,
                            height: 80,
                            borderRadius: 40,
                            alignSelf: "center",
                            marginBottom: 20
                        }}
                    >
                        <Text style={{ color: "white", fontSize: 28 }}>JD</Text>
                    </View>
                    <Button title="Log Out" onPress={this.handleClick} />
                </Card>
            </View>
        );
    }
}

const mapDispatchToProps = dispatch => {
    return {
        logOut: function() {
            dispatch(logOut());
        }
    };
};

const Profile = connect(null, mapDispatchToProps)(ProfileWrap);

export default Profile;

您的 mapDispatchToProps 应该返回一个具有 函数 的对象。按照您现在的方式,logOut() 将立即被调用,因为它不在函数内部。将其更改为此应该修复它:

const mapDispatchToProps = dispatch => {
    return { 
        logOut: function () {
            dispatch(logOut());
        }
    };
};

这里有一个更简洁的方法:

const mapDispatchToProps = dispatch => ({ 
    logOut() {
        dispatch(logOut());
    }
});

此外,您在 mapDispatchToProps 前面缺少 const,但这应该不会影响任何事情。

编辑:

您现在不必使用它,但它在将来会有帮助 - 如果您的组件仅使用 render 方法,您可以将其更改为无状态功能组件。这是目前推荐的创建组件的方式:

const ProfileWrap = props => (
  <View style={{ paddingVertical: 20 }}>
      <Card title="Profile">
          <View
              style={{
                  backgroundColor: "#bcbec1",
                  alignItems: "center",
                  justifyContent: "center",
                  width: 80,
                  height: 80,
                  borderRadius: 40,
                  alignSelf: "center",
                  marginBottom: 20
              }}
          >
              <Text style={{ color: "white", fontSize: 28 }}>JD</Text>
          </View>
          <Button title="Log Out" onPress={props.logOut} />
      </Card>
  </View>
);