何时在 React 应用程序中使用 Dispatcher

Posted

技术标签:

【中文标题】何时在 React 应用程序中使用 Dispatcher【英文标题】:When to use Dispatcher in React Application 【发布时间】:2018-09-21 08:44:08 【问题描述】:

我在 ReactJS 中使用 Dispatcher 时遇到了一些问题。因此,我尝试从商店中删除此调度程序,但商店仍然运行良好。正确存储我的数据并且更改事件运行良好。

现在我在我们的应用程序中使用调度程序有点困惑。

这里是代码

MenuList 是我的组件,我在其中调用MenuStore.getMenuFromAPI(),之后我还添加了MenuStore 的onChange 事件。

class MenuList extends React.Component

  constructor()
    super();
    this.state = open:false, menuList:"",numbering:-1
  

  componentWillMount()
    var that = this;
    MenuStore.getMenuFromAPI();
    MenuStore.on("change", ()=> 
      that.setState(menuList:MenuStore.getMenu());
    )
  

  componentWillReceiveProps(nextProps)
    if(nextProps.show!=this.props.show)
      this.setState(open:nextProps.show);
    
  

  render()
    const  classes  = this.props;

    return (

      <div>My MEnu</div>
    )
  

菜单商店

class MenuStore extends EventEmitter 
  constructor() 
    super();
    this.menu = null;
  

  getMenu()
    return this.menu;
  

  getMenuFromAPI()
    var that = this;
    $.ajax(
      type: "POST",
      url: LinkConstants.GETMENU,
      headers: 
          'Accept': 'application/json',
          'Content-Type': 'application/json'
      ,
      data: "",
      dataType :"json",
      success: function(response) 
        that.menu =response;
        that.emit("change");
      .bind(this),
      error: function(xhr, status, err) 
        console.log(err);
      .bind(this)
    );
  

  // handleAction(action) 
  //   switch (action.type) 
  //     case ActionTypes.MENU: 
  //       this.getMenuFromAPI();
  //       break;
  //     
  //   
  // 



const menuStore = new MenuStore;
//Dispatcher.register(menuStore.handleAction.bind(menuStore));
export default menuStore;

如您所见,我注释掉了 Dispatcher.register 行和 handleAction 函数。

上面的代码可以正常工作,但我想知道为什么在这里使用 Dispatcher?

如果我只想将我的数据存储在 MenuStore 中并从应用程序中任何组件上的 MenuStore 取回它。因此有必要使用调度程序和操作,或者只使用商店。

请通过适当的示例或案例场景(如果可能)澄清我的疑问,何时使用调度程序和操作或何时仅使用商店。

【问题讨论】:

【参考方案1】:

在您的示例中,您根本没有使用 Redux,您刚刚创建了一个用作获取数据的简单存储的类,但您没有使用任何 Redux 功能。

Redux 是关于一个存储的,它只是一个代表应用程序状态树的普通对象。为了改变这个状态,你派发动作。动作只是描述发生的事情的简单对象。每个动作都有一个描述动作的type 字段。动作由 reducer 处理,它们是获取当前状态和分派动作并决定应用程序下一个状态的函数。这就是 Redux 的几句话。

Redux 存储有一个名为 dispatch 的方法,用于调度操作。正如 Redux 文档中提到的,这是触发状态更改的唯一方法。

假设我们有一个 TODO 列表应用程序。我们的商店可以表示为一个字符串数组(待办事项)。

要向列表中添加新项目,我们将定义一个简单的操作:

const addItemAction = (item = '') => (
    type: 'ADD_ITEM',
    data: item,
);

可以在您的组件方法之一中调度此操作,该方法将附加到某些键盘/鼠标事件:

class TodoList extends React.Component 
    ...
    // addNewItem is called with a value from a text field
    addNewItem(item) 
        store.dispatch(addItemAction(item));
    
    ...

正如我上面提到的,状态是由 reducer 函数改变的。 reducer 决定是否改变状态以及如何改变它。如果调度的动作不应该改变状态,它可以只返回接收到的状态:

function todoReducer(state = [], action) 
    switch(action.type) 
        case 'ADD_ITEM':
            return [...state, action.data];
        break;
        default:
            return state;
    

Reducer 被传递给 createStore 方法:

import  createStore  from 'redux'    
const store = createStore(todoReducer);

在 TodoList 组件中,您可以使用 store.subscribe 方法订阅商店,该方法接受一个回调函数,每次商店状态更改时都会调用该回调函数。当检测到更改时,您可以调用组件的 setState 来设置组件状态列表并导致组件重新呈现:

class TodoList extends React.Component 
    ....
    componentDidMount() 
        this.storeSubscription = store.subscribe((state) => 
            // For the example I'm just setting the state (list of todos) 
            // without checking if it changed or not
            this.setState(
                todos: state,
            );
        );
    

    render() 
        return this.state.todos.map(todo => <div>todo</div>);
    
    ....

这是一个几乎完整的使用 Redux 的例子。我们使用 action 来描述我们应用程序中的一个事件,我们使用 store 的 dispatch 方法将 action 分发到 store,Redux 将在收到新的 action 时调用 reducer,reducer 计算新的状态,我们的组件检测到变化通过使用商店的subscribe 方法。

在更复杂的应用程序中需要考虑和处理的事情更多。你可能会有一个更复杂的状态树,所以你需要额外的 reducer 来处理计算状态。此外,在某些步骤中,您需要考虑使用一些帮助程序来减少订阅状态更改和检测更改的开销。

在更复杂的应用程序中,您可能会通过绑定库(例如react-redux)将组件连接到商店,因此您的组件将通过道具接收商店的相关部分,这将节省订阅商店更改的开销并决定何时重新渲染组件。

我建议您观看 Dan Abramov 的“Redux 入门”,以进一步了解什么是 Redux 以及如何使用它。 Getting started with Redux

【讨论】:

以上是关于何时在 React 应用程序中使用 Dispatcher的主要内容,如果未能解决你的问题,请参考以下文章

为啥以及何时需要在 React 中绑定函数和事件处理程序?

React - 何时使用钩子,何时使用 HOC

何时使用 React [关闭]

我应该何时将 Redux 添加到 React 应用程序?

如何在 React Native 中检测键盘何时打开或关闭

何时使用inputRef.current而不是this.inputRef React.js?