【问题标题】:dispacthing actions creator gets called twice using componentWillMount调度动作创建者使用 componentWillMount 被调用两次
【发布时间】:2017-03-08 07:17:05
【问题描述】:

我使用 componentWillMount 方法调用 action creator, 然后它被调用了两次。看看下面的结果截图。

这是我的行动创作者

export function fetchAdmin(){
    return (dispatch)=>{
        axios.get(`${Config.API_URL}/admin`,{
            headers: { authorization: localStorage.getItem('token')}
        })
            .then(response => {
                   return dispatch({
                        type: FETCH_DATA,
                        payload: response.data
                    });
                }
            )
            .catch(response => {
                console.log(response);
            });
    }
}

这是我的reducer

import { FETCH_DATA } from '../actions/types';

export function admin(state= {}, action){
    switch(action.type){
        case FETCH_DATA:
            return {...state, lists: action.payload };
        default:
            return { state, lists: 'YEY!'}
    }


}

这是我的容器,也是我使用 componentWillMount 调用动作创建者的方式。

import React, { Component } from 'react';
import { Link } from 'react-router';
import { connect } from 'react-redux';
import * as actions from 'actions/admin_action';


class Admin extends Component{
    componentWillMount(){
        this.props.fetchAdmin()
    }
    renderData(){
        var lists = this.props.lists;
        console.log(lists);
    }
  render(){

        return(
          <div>
            {this.renderData()}
          </div>
        )
  }

const mapStateToProps = (state) => {
     return { lists: state.admin.lists };
}

export default connect(mapStateToProps, actions)(Admin);

从截图中我假设 render() 被调用了两次。第一个调用转到默认操作创建者,因此结果是“是!”第二个是有效的。

有人可以向我解释为什么 componentWillMount 会这样执行,实际上在第一次渲染中我只想让我的数组不是“YEY!”如何解决这个问题呢?谢谢。

【问题讨论】:

  • 不建议在componentWillMount触发数据加载。你应该在componentDidMount
  • 真的吗?为什么? @just-boris
  • 这个 Twitter 线程包含一些解释 twitter.com/dan_abramov/status/790581793397305345
  • 另外官方文档:facebook.github.io/react/docs/…componentWillMount:避免在此方法中引入任何副作用或订阅。 componentDidMount:如果需要从远程端点加载数据,这里是实例化网络请求的好地方。

标签: javascript reactjs redux react-redux


【解决方案1】:

这里没有问题!当你的组件第一次渲染时,它在逻辑componentWillMount完成之前到达渲染,所以:

首次渲染:您的组件被渲染,而全局状态下的lists 是默认值,等于YEY!

第二次渲染:当数据获取成功后,reducer 会在全局状态下lists 中的reducer 发生变化,然后你的组件会检测到由于@987654325 而发生的变化@ 从全局状态中获得了lists

不用说 React 组件会在 propsChange 上重新渲染,这就是为什么有一个方法 componentWillReceiveProps 以便您可以在每次 props 更改时添加一些逻辑(如果需要)。

此行为允许您处理等待数据被获取的情况:

  • 添加加载微调器。
  • 渲染您的布局。
  • 渲染页面中的其他组件。

【讨论】:

  • 我应该把 componentWillReceiveProps 放在哪里?我将 componentWillMount 更改为 componentWillReceiveProps 结果只是“YEY”@Basim
  • 如果您的用例需要一些逻辑,这很有用,但在这种情况下我不这么认为。
  • 实际上在第一次渲染中我只想要我的数组而不是“YEY!”如何解决这个问题呢? @Basim
  • 在你的默认情况下,reducer 只返回 return state 的状态,但你需要初始化 lists 数组,所以它应该是 return { state, lists: []}
  • 我更改了它,结果是默认减速器上的空数组 []。是否可以只调用FETCH_DATA,我不希望我的容器调用默认减速器。可能吗? @Basim
【解决方案2】:

Javascript 是异步的。您正在执行的 HTTP 请求是异步的。这意味着 Javascript 继续执行,而 HTTP 请求仍处于未决状态。

所以 React 已经在状态仍然是 'Yey' 的时候渲染了。这就是它应该的样子,也是 Redux 的美妙之处,动作就是一劳永逸,而不是阻塞。如果 React 会等待 HTTP 请求完成,用户体验会很糟糕!

如果您不希望它呈现“Yey”。您应该在请求仍处于待处理状态时显示加载程序或其他内容。

【讨论】:

  • 谢谢先生的解释,这让我现在很清楚。 ^^
猜你喜欢
  • 2016-12-13
  • 2013-11-06
  • 1970-01-01
  • 1970-01-01
  • 2017-06-19
  • 2020-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多