简体   繁体   English

在componentDidMount上调度一个动作(react / redux)

[英]dispatch an action on componentDidMount (react/redux)

I am relativity new to react/redux. 我是反应/减少的新相对论。 There for I want to ask a (perhaps a philosophic) question. 因为我想问一个(也许是一个哲学的)问题。

Is it ok to to dispatch an action (eg to trigger an api-call) on componentDidMount of a react component? 是否确定派遣一个动作(例如触发的API调用)上componentDidMount一个反应成分的?

If not, why and where should I dispatch the action? 如果没有,我为什么要在哪里发布行动?

If yes, then no further questions? 如果是,那么没有其他问题吗? :) :)

Yes, dispatching an action on componentDidMount() is OK, and even the recommended thing to do since it will not slow down the initial UI render. 是的,在componentDidMount()上调度操作是可以的,甚至是推荐的事情,因为它不会减慢初始UI渲染速度。

Since the function runs after the component has initially rendered, keep in mind that you may have sometime between the moment the component is rendered, and the moment you receive the data from the api call. 由于函数在组件最初呈现后运行,请记住,在组件呈现的时刻和从api调用接收数据的那一刻之间可能会有一段时间。

Yes, you should definately use the componentDidMount hook. 是的,你应该肯定使用componentDidMount钩子。

A typical use case might be : 典型的用例可能是:

  • Component appears on screen, eg a table 组件出现在屏幕上,例如桌子
  • Request to the server is triggered to get data 触发对服务器的请求以获取数据
  • A spinner/loader is shown to cover the component 显示旋转器/装载器覆盖组件
  • data comes back 数据回来了
  • spinner is removed and data is shown in the table. 删除了微调器,数据显示在表中。

I know its a bit long, but I was working myself on this type of problem for a while, so I thought I would share the following pattern ;) 我知道它有点长,但我一直在研究这类问题,所以我想我会分享以下模式;)

When the component mounts then a fetch data action is triggered. 当组件安装时,则触发获取数据操作。 An 'isFetching' value in the application state determines whether the spinner is shown or not (I think i used 'advanced-loader' or some such library) 应用程序状态中的'isFetching'值确定是否显示微调器(我认为我使用'advanced-loader'或某些此类库)

export default class MyComponent extends React.Component {

  componentDidMount() {
    AppDispatcher.dispatch({
      type: ActionTypes.FETCH_DATA,
    });
  }

  render() {
    let isFetching = this.props.my.application.path.isFetching;
    return (
      <Loader show={isFetching} message={'loading'}>
        <div>
          My Component
        </div>
      </Loader>
    );
  }
}

Then in the store the FETCH_DATA triggers a request : 然后在商店中FETCH_DATA触发一个请求:

class AppStore extends ReduceStore {

  //......

  reduce(state, action) {

    let imState = Immutable.fromJS(state);

    switch (action.type) {

      //......

      case ActionTypes.FETCH_DATA:
        doGetRequest('/url_to_service');
        break;

      //......
    }
    return imState.toJS();
  }
}

The request would look something like this : 请求看起来像这样:

function doGetRequest(endpoint, params = {}) {

  //request is some kind of AJAX library. In my case 'superagent'
  request.get(endpoint)
    .set('Accept','application/json')
    .query(params)
    .end(
      (err, res) => {
        if (res && res.ok) {
          receiveData(endpoint, "SUCCESS", res);
        } else {
          receiveData(endpoint, "FAIL");
    }});
}

Upon completion it would then dispatch another action. 完成后,它将发出另一个动作。

function receiveData(endpoint, state, responseData) {
  AppDispatcher.dispatch(
    {
      type: ActionTypes.SERVER_RESPONSE,
      endpoint: endpoint,
      state: state,
      payload: responseData
    }
  );
}

Going back to the store, the second action is caught and the isFetching flag is set to false, then the application data is handled. 返回商店,捕获第二个操作并将isFetching标志设置为false,然后处理应用程序数据。

  reduce(state, action) {

    let imState = Immutable.fromJS(state);

    switch (action.type) {

      //......


      case ActionTypes.SERVER_RESPONSE: {

        imState = imState.setIn(['my','application','path', 'isFetching'], false)

        if (action.state == "SUCCESS") {
            //do something with the action.response data (via state update)
        }else if (action.state == "FAIL") {
            //maybe show an error message (via state update)
        }
        break;
      }
    }
    return imState.toJS();
  }
}

.... so this typical use case uses two 'actions', the first action being triggered from the componentDidMount method, and the second action is triggered after the request finishes. ....所以这个典型的用例使用两个'actions',第一个动作是从componentDidMount方法触发的,第二个动作是在请求完成后触发的。

Hope this pattern helps :) 希望这种模式有帮助:)

According to the official React documentation, componentDidMount is exactly the right place to do so: 根据官方的React文档, componentDidMount正是这样做的正确位置:

componentDidMount() is invoked immediately after a component is mounted. 在装入组件后立即调用componentDidMount()。 Initialization that requires DOM nodes should go here. 需要DOM节点的初始化应该放在这里。 If you need to load data from a remote endpoint, this is a good place to instantiate the network request. 如果需要从远程端点加载数据,这是实例化网络请求的好地方。

Official React Documentation for componentDidMount() - componentDidMount()官方React文档

When using routes another recommended way to dispatch an action would be the routes-method "onEnter". 当使用路由时,另一种推荐的方式来分派动作将是routes-method“onEnter”。 This is in order to make the component not dependent from actions (or api-calls). 这是为了使组件不依赖于动作(或api-calls)。

I personally think both methods (componentDidMount vs. onEnter) are ok. 我个人认为这两种方法(componentDidMount与onEnter)都可以。 It is left to the programmer to choose which solution is best for his application. 由程序员选择哪种解决方案最适合他的应用程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM