React-Redux Counter 示例动作触发两次 [英] React-Redux Counter example action firing twice

查看:45
本文介绍了React-Redux Counter 示例动作触发两次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

解决方案

您收到重复调度的原因是您编写 mapDispatchToProps 对象的方式(以及看似无害的使用双箭头语法).

双箭头语法不带大括号,如() =>;value,转化为function { return value }.

因此,onIncrement 实际上不再是一个看起来像 { store.dispatch(...) } 的函数——它实际上是调度调用的返回值.在这种情况下,这只是分派的操作.

如果我们编写 onIncrement 看起来像这样(它只返回操作对象):

onIncrement: () =>{返回 {类型:增量"}}

我们最终会在按钮按下时正确调度操作.

这导致了你的双重分派 - onIncrement 首先调用 store.dispatch 然后从返回的对象中旋转另一个分派.

无论如何,您可以通过在 onIncrement() 中添加大括号来解决这个问题:

onIncrement: () =>{store.dispatch({类型:'增量'});},

您也可以简单地仅返回操作对象,如前面所示.

https://codesandbox.io/s/jvj6o043yv

I'm trying to grok the basics of react-redux connect, Provider, and mapStateToProps and MapDispatchToProps using the very simple Counter example. The point of the exercise is to have the props and actions injected into the Counter component.

The issue I'm seeing is that my actions are firing twice on each button click. I'm a Redux noob so I'm sure (I hope) it's a fairly basic error. I'd appreciate any pointers to where I went wrong. Thanks in advance.

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { connect } from 'react-redux'
import { createStore, applyMiddleware } from 'redux';
import { createLogger } from 'redux-logger';


// Reducer
const counter = (state = 0, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1;
    case 'DECREMENT':
      return state - 1;
    default:
      return state;
  }
}

// store setup
const configureStore = () => {
  const middlewares = [];
  if (process.env.NODE_ENV !== 'production') {
    middlewares.push(createLogger());
  }
  return createStore(
    counter,
    applyMiddleware(...middlewares)
  );
};
const store = configureStore();

// functional component
let Counter = ({
  currCounter,
  onIncrement,
  onDecrement
}) => (
  <div>
    <h1>{currCounter}</h1>
    <button onClick={onIncrement}>+</button>
    <button onClick={onDecrement}>-</button>
  </div>
);

// Connect logic
const mapStateToProps = (state) => ({
  currCounter: state
})
const mapDispatchToProps = {
  onIncrement: () =>
    store.dispatch({
      type: 'INCREMENT'
    }),
  onDecrement: () =>
    store.dispatch({
      type: 'DECREMENT'
    }),
}
Counter = connect(
  mapStateToProps,
  mapDispatchToProps
)(Counter)

// Entry point
const render = () => {
  ReactDOM.render(
    <Provider store={store}>
      <Counter />
    </Provider>,
    document.getElementById('root')
  );
};

store.subscribe(render);
render();

解决方案

The reason you're getting a duplicated dispatch is because of the way you've written your mapDispatchToProps object (and seemingly innocent use of double arrow syntax).

Double arrow syntax without the braces, as in() => value, translates into function { return value }.

Therefore, onIncrement isn't actually a function that looks like { store.dispatch(...) } anymore - it's actually the return value of the dispatch call. In this case, that's simply the dispatched action.

If we write onIncrement to look something like this (which just returns the action object):

onIncrement: () => {
    return {
      type: "INCREMENT"
    }
}

we end up with a properly dispatched action on button presses.

That's causing your double dispatch - onIncrement is first calling store.dispatch and then spinning another dispatch from the returned object.

Regardless, you can solve this pretty simply by adding braces to your onIncrement():

onIncrement: () => {
    store.dispatch({
      type: 'INCREMENT'
    });
},

You can also simply return just the action object, as shown earlier.

这篇关于React-Redux Counter 示例动作触发两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆