首页 > 解决方案 > 这是使用 react redux 发出 axios GET 请求的正确方法吗?

问题描述

我是一个初学者,所有这些都是非常新的。我已经调试了一段时间,我似乎无法修复这个错误。我会很感激一些指示。

其他帖子和放置请求正在工作,但是我尝试做一个获取请求。

这是使用 React Developer Tools 组件选项卡
的 Home 中的 props 片段: Home 的 props

redux 的操作类型:client\src\actions\types.js

export const GET_ERRORS = "GET_ERRORS";

export const USER_LOADING = "USER_LOADING";
export const SET_CURRENT_USER = "SET_CURRENT_USER";

export const GET_USERDATA = "GET_USERDATA";
export const UPDATE_USERDATA = "UPDATE_USERDATA";

redux 的操作:client\src\actions\userdataActions.js

import axios from "axios";

import {
    GET_ERRORS,
    GET_USERDATA,
    UPDATE_USERDATA
} from "./types";

// Get userdata with username
export const getUserData = (userData) => dispatch => {
    return axios
        .get("/api/users/userdata", userData)
        .then(response => {
            dispatch(fetchUserData(response.data)); 
        })
        .catch(err => {
            dispatch(getErrors(err));
        });
};

// Put new userdata with username
export const updateUserData = (newUserData) => dispatch => {
    axios
        .put("/api/users/userdata", newUserData)
        .then(response => {
            dispatch(updatingUserData());
        })
        .catch(err => {
            dispatch(getErrors(err));
        });
};

export const fetchUserData = userData => {
    return {
        type: GET_USERDATA,
        payload: userData
    }
};

export const updatingUserData = () => {
    return {
        type: UPDATE_USERDATA
    };
};

// Get Errors 
export const getErrors = err => {
    return {
      type: GET_ERRORS,
      payload: err.response.data
    };
};

redux 的减速器:client\src\reducers\dataReducers.js

import {
    GET_USERDATA, 
    UPDATE_USERDATA
} from "../actions/types";

const isEmpty = require("is-empty");

const initialState = {
    hasUserData: false,
    user: {},
    updated: false,
};

export default function(state = initialState, action) {
    switch (action.type) {
        case GET_USERDATA:
            return {
                ...state,
                hasUserData: !isEmpty(action.payload),
                user: action.payload
            };
        case UPDATE_USERDATA:
            return {
                ...state,
                updated: true,
            };
        default:
            return state;
    }
}

使用反应的前端:client\src\components\home\Home.js

import React, { Component } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { logoutUser } from "../../actions/authActions";
import { getUserData, updateUserData } from "../../actions/userdataActions";

import Logout from "./Logout.js";
import Coins from "./Coins.js";
import Happiness from "./Happiness.js";

class Home extends Component {
    constructor(props) {
        super(props);
        this.name = this.props.auth.user.name;
        this.updateCoins = this.updateCoins.bind(this);
        this.updateHappiness = this.updateHappiness.bind(this);
    }

    componentDidMount() {
        if (!this.props.userdata.hasUserData) {
            const userData = { name: this.name };
            this.props.getUserData(userData); 
        }  
    }

    onLogoutClick = e => {
        e.preventDefault();
        this.props.logoutUser();
    };    

    updateCoins(newCoins) {
        const userData = {
            name: this.name,
            coins: newCoins,
        };
        this.props.updateUserData(userData); 
    }

    updateHappiness(newHappiness) {
        const userData = {
            name: this.name,
            happiness: newHappiness,
        };
        this.props.updateUserData(userData); 
    }

    render() {
        return (
            <div>  
                <Coins coins={this.props.userdata.user.coins} updateCoins={this.updateCoins} />
                <Happiness happiness={this.props.userdata.user.happiness} updateHappiness={this.updateHappiness} />
                <Logout onLogoutClick={this.onLogoutClick} />           
            </div>
        );
    }
}

Home.propTypes = {
    logoutUser: PropTypes.func.isRequired,
    getUserData: PropTypes.func.isRequired,
    updateUserData: PropTypes.func.isRequired,
    auth: PropTypes.object.isRequired,
    errors: PropTypes.object.isRequired,
    userdata: PropTypes.object.isRequired
};

const mapStateToProps = state => ({
    auth: state.auth,
    errors: state.errors,
    userdata: state.userdata
});

export default connect(
    mapStateToProps,
    { logoutUser,
      getUserData,
      updateUserData }
)(Home);

标签: reactjsreact-reduxaxiosredux-thunk

解决方案


我不会使用这样的 ajax 服务。反而

  1. 使用一个服务模块来封装所有的ajax调用并处理异常。这些服务的结果是带有原始数据的 Promise

  2. 在您的 thunk 操作中,然后使用服务获取数据并在必要时调度以更新存储

  3. 组件只是像往常一样使用 thunk 动作。这有助于增加关注点的分离,更容易测试和维护。


const handleError = (error) => {
   console.log(error);
};

export const getUserData = (userData) => {
    return axios
        .get("/api/users/userdata", userData)
        .then(response => (response.data))
        .catch(err => {
            handleError(err);
        });
};

...
// later in thunk action creator 

const updateUserDataThunk = async (userData) => dispatch => {
    const apiData = await getUserData(userData);
    dispatch(updateUser(apiData));
}

...
// in component

componentDidMount(){
  dispatch(updateUserDataThunk(this.props.userData));
}


推荐阅读