【问题标题】:React Native Advice - Firing Redux Action OnPress Dispatch ActionReact Native Advice - 触发 Redux Action OnPress Dispatch Action
【发布时间】:2018-09-03 06:42:20
【问题描述】:

我是在 React Native 应用程序中使用 Redux 的新手。当用户在应用程序中按下按钮时,我需要一些关于如何触发我的 redux 操作的建议。

我有一个登录屏幕,用户可以在其中输入他们的用户名和密码,这会在按下按钮时触发 fetchData Redux 操作。 fetchData 操作使用 Redux Saga 发出 API 请求以验证用户,如果有效,将返回“auth_token”。

我想要实现的是,如果返回身份验证令牌,用户将被重定向到我的 onPress 函数中的另一个屏幕。

到目前为止,这是我的代码...

登录屏幕

import PropTypes from 'prop-types';
import React, { Component} from 'react';
import { Container } from '../components/Container';
import { StatusBar, Text, TextInput, Button } from 'react-native';
import { setItem } from '../storage/sensitive'
import { connectAlert } from "../components/Alert";
import { connect } from "react-redux";
import { fetchData } from "../redux/actions/userLogin";

class SignIn extends Component {
    static propTypes = {
        navigation: PropTypes.object,
        dispatch: PropTypes.func,
        authToken: PropTypes.string,
        //appData: PropTypes.object
    };

    state = {
        username: '',
        password: '',
        error: '',
        appData: {}
    }

    componentWillMount() {

    }

    onPressSignIn = () => {
        // Check if the username and password fields are entered.
        if (this.state.username === '' || this.state.password === '') {
            this.setState({error: 'Please ensure you have entered a username and password '});
        }
        else {
            // Remove error message if one was rendered previously.
            this.setState({error: ''})

            // Send user credentials to loginUser function to retrieve Authentication Token.
            this.props.dispatch(fetchData(this.state.username, this.state.password));

            // HOW?: Output 'this.props.appData.data.user.auth_token' to determine whether the user is valid
            //        If valid redirect to another screen.
        }

    };

    render() {
         let test = this.props.appData;
         console.log('Get Auth Token', test.data.user ? test.data.user.auth_token : 'no token');
        return (
            <Container>
                <StatusBar barStyle="default" />
                <Text>Sign In</Text>
                <TextInput style={{height: 40, borderColor: 'gray', borderWidth: 1}}
                           placeholder="Username"
                           value={this.state.username}
                           email-address={true}
                           onChangeText={username => this.setState({username})} />
                <TextInput style={{height: 40, borderColor: 'gray', borderWidth: 1}}
                           placeholder="Password"
                           value={this.state.password}
                           onChangeText={password => this.setState({password})}
                           secureTextEntry={true} />
                <Button onPress={this.onPressSignIn} title="Sign In" color="#841584" accessibilityLabel="Sign in to your account" />
                {this.state.error &&
                    <TextInput value={this.state.error} />
                }
                {this.state.appData.isFetching && <TextInput value='Loading' />}
            </Container>
        );
    }
}

const mapStateToProps = (state) =>  {
    console.log('mapStateToProps', state);
    return {
        appData: state.userLoginReducer
    }
}

export default connect(mapStateToProps)(connectAlert(SignIn));

减速器(如果有帮助)

import { FETCHING_DATA, FETCHING_DATA_SUCCESS, FETCHING_DATA_FAILURE } from '../actions/userLogin'

const initialState = {
    data: [],
    username: '',
    password: '',
    dataFetched: false,
    isFetching: false,
    error: false
}

const userLoginReducer = (state = initialState, action) => {
    switch (action.type) {
        case FETCHING_DATA:
            return {
                ...state,
                data: [],
                isFetching: true,
                username: action.username,
                password: action.password
            }
        case FETCHING_DATA_SUCCESS:
            return {
                ...state,
                isFetching: false,
                data: action.result
            }
        case FETCHING_DATA_FAILURE:
            return {
                ...state,
                isFetching: false,
                error: true
            }
        default:
            return state
    }
}

export default userLoginReducer;

当用户按下onPressSignIn 函数时,我注意到,“auth_token”永远不会返回。但是,它会在 render() 区域内返回。

此时我是否需要进行检查以确定用户是否成功登录?只有在这里我才能从我的 Redux 操作类型中获得成功响应。

【问题讨论】:

    标签: react-native redux react-redux redux-saga


    【解决方案1】:

    我对@9​​87654322@ 不是很熟悉,但我会告诉你,如果我的 fetch 请求返回了 Promise 或者没有返回,我会怎么做。如果您的 fetch 请求返回 Promise,它看起来像这样(请记住,我通常使用 bindActionCreators 方法将调度映射到道具):

     onPressSignIn = () => {
       if (this.state.username === '' || this.state.password === '') {
         this.setState({error: 'Please ensure you have entered a username and password '});
       } else {
         this.setState({error: ''})
    
         fetchData(this.state.username, this.state.password)
           .then(res => {
             // Here you can have all kinds of logic to decide if
             // redirect should occur or not
             if (res.isUserAuthenticated) redirectTo('/anotherScreen');
           });
     };
    

    否则我会简单地使用componentDidUpdate:

    componentDidUpdate() {
      // At this point your props are up to date as this lifecycle method
      // is called every time your component receives new props
      const test = this.props.appData;
      if (test.data.user.auth_token) redirectTo('/anotherScreen');
    }
    

    在这种情况下,您的 onPressSignIn 不会改变。

    【讨论】:

    • 这看起来非常优雅,可以满足我的需求。你认为我使用 Redux 过度设计了我的解决方案吗?我质疑我是否只是因为它似乎是推荐的状态管理方法而使用它。
    • 嗯,我不了解您的应用程序整体,所以我不能给你一个直接的答案。我建议直接从文档中阅读一些文章(这里是一个有用的链接redux.js.org/#before-proceeding-further)。这一切都取决于您的应用程序的规模以及您在状态管理、道具钻探、状态提升等方面面临的问题......
    • 如果您认为此答案令人满意,也将其标记为正确! =D
    猜你喜欢
    • 2019-08-24
    • 2021-11-01
    • 2016-08-16
    • 2022-01-02
    • 1970-01-01
    • 1970-01-01
    • 2021-11-05
    • 2016-12-10
    • 1970-01-01
    相关资源
    最近更新 更多