【问题标题】:How I should dispatch the action to fetch the data using react components and redux?我应该如何调度操作以使用反应组件和 redux 获取数据?
【发布时间】:2020-09-07 06:47:02
【问题描述】:

我正在使用 axios 获取数据,然后使用 redux 将状态映射到道具,但我遇到了问题。如果我在componentDidUpdate() 中分派动作,动作将无限期执行,如果我使用constructor(props),我会得到props 的未定义值,我也尝试过componentDidMount,但我得到了未定义的概率值。有没有办法使用反应组件调度动作?

我在第二次渲染中从state 获得了正确的数据。

import React, { Component } from 'react'
import {connect} from 'react-redux'
import { getUserPosts } from '../../actions'

class UserPosts extends Component {

    //UNSAFE_componentWillMount() {

    //}
    constructor(props) {
        super(props);
        console.log(props);
    }


    componentDidUpdate() {
        //this.props.dispatch(getUserPosts(this.props.user_reducer.login?.user._id));
    }

    showUserPosts = (user) => (

        Array.isArray(user.userPosts) ?
          user.userPosts.map((item, i) => (
                <tr key={i}>
                <td>{i}</td>
                <td>author</td>
                <td>date</td>
                </tr>    

          ))
        : null    

    )

    render() {
        let user = this.props.user_reducer;
        //console.log(user.userPosts);
        return (
            <div>
               <div className="user_posts">
                   <h4>Your reviews:</h4>
                   <table>
                       <thead>
                           <tr>
                               <th>Name</th>
                               <th>Author</th>
                               <th>Date</th>
                           </tr>
                       </thead>
                       <tbody>
                           {this.showUserPosts(user)}
                       </tbody>
                   </table>
               </div>
            </div>
        )
    }
}

function mapStateToProps(state) {
    //console.log(state);
    return {
        user_reducer: state.user_reducer
    }
}

export default connect(mapStateToProps)(UserPosts)

行动:

export function getUserPosts(userId) {
    const req = axios.get(`/api/user_posts?user=${userId}`)
                .then(res => res.data);

    return {
        type: 'GET_USER_POSTS',
        payload: req
    }
}

减速器:

export default function(state = {}, action) {
    switch(action.type) {
        case 'USER_LOGIN':
            return {...state, login: action.payload}
        case 'USER_AUTH':
            return {...state, login: action.payload}
        case 'GET_USER_POSTS':
            return {...state, userPosts: action.payload}
        default: return state; 
    }
}

【问题讨论】:

  • 你在action.js中使用了dispatcher
  • 不,我在上面的组件中使用它
  • 我们可以看看你的 store/reducer 设置吗?另外,您是否将应用程序包装在 Provider 中?
  • 你能从路由器参数之类的任何地方获取用户ID吗?否则,可能会重组事物以不传递 id 并让商店根据通过先前在后台调度设置的用户 id 请求用户特定数据,然后将状态映射到这个新属性的道具,例如 userDetail。
  • 我的意思不是来自商店,而是来自其他来源。您是否正在使用 react-router-dom 或类似的东西,例如,您可以从 url 参数中获取_id?您所在的 _id 属性嵌套得很深。在组件挂载之前,它可能不可用。

标签: reactjs redux


【解决方案1】:

派发动作的正确位置是在 componentDidMount 中。但是,由于您的数据获取是异步的,因此您必须在 reducer 中保持加载状态,直到您的数据被获取

export default function(state = {isPostLoading: true}, action) {
    switch(action.type) {
        case 'USER_LOGIN':
            return {...state, login: action.payload}
        case 'USER_AUTH':
            return {...state, login: action.payload}
        case 'GET_USER_POSTS':
            return {...state, userPosts: action.payload, isPostLoading: false}
        default: return state; 
    }
}

class UserPosts extends Component {

    constructor(props) {
        super(props);
        console.log(props);
    }


    componentDidMount() {
       this.props.dispatch(
           getUserPosts(this.props.user_reducer.login?.user._id) 
      );
    }
    componentDidUpdate(prevProps) {
       if(this.props.user_reducer.login?.user._id !== prevProps.user_reducer.login?.user._id) {
          this.props.dispatch(getUserPosts(this.props.user_reducer.login?.user._id));
       }
    }

    showUserPosts = (user) => (

        Array.isArray(user.userPosts) ?
          user.userPosts.map((item, i) => (
                <tr key={i}>
                <td>{i}</td>
                <td>author</td>
                <td>date</td>
                </tr>    

          ))
        : null    

    )

    render() {
        let user = this.props.user_reducer;
        if(user.isPostLoading) {
            return <div>Loading....</div>
        }
        return (
            <div>
               <div className="user_posts">
                   <h4>Your reviews:</h4>
                   <table>
                       <thead>
                           <tr>
                               <th>Name</th>
                               <th>Author</th>
                               <th>Date</th>
                           </tr>
                       </thead>
                       <tbody>
                           {this.showUserPosts(user)}
                       </tbody>
                   </table>
               </div>
            </div>
        )
    }
}

function mapStateToProps(state) {

    return {
        user_reducer: state.user_reducer
    }
}

export default connect(mapStateToProps)(UserPosts)

【讨论】:

  • 谢谢,但第一次渲染我没有得到数据,我在第二次渲染中得到它。 componentDidMount 中的 user_reducer 属性为空。旧代码使用的是componentWillMount,现在没有使用
  • 初始渲染时登录值是否为真
  • 是的,登录值是假的,看来你现在知道我正在关注教程 :) 现在可以使用了,谢谢
  • 好像你需要结合使用 componentDidMount 和 componentDidUpdate 因为你的登录是假的
  • 很高兴能帮上忙
猜你喜欢
  • 1970-01-01
  • 2017-10-21
  • 2019-02-07
  • 2021-01-22
  • 2017-09-08
  • 2017-12-27
  • 2017-04-04
  • 2017-07-11
  • 1970-01-01
相关资源
最近更新 更多