首页 文章

React-Redux Counter示例动作两次触发

提问于
浏览
2

https://codesandbox.io/s/jvj6o043yv

我正在尝试使用非常简单的Counter示例来理解react-redux连接,Provider,mapStateToProps和MapDispatchToProps的基础知识 . 练习的目的是将道具和动作注入Counter组件 .

我看到的问题是我的操作在每次点击按钮时都会触发两次 . 我是Redux noob,所以我确信(我希望)这是一个相当基本的错误 . 我很欣赏任何指向错误的地方 . 提前致谢 .

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();

double action

3 回答

  • 1

    你're getting a duplicated dispatch is because of the way you'写了你的 mapDispatchToProps 对象的原因(看似无辜地使用双箭头语法) .

    没有大括号的双箭头语法,如 () => value ,转换为 function { return value } .

    因此, onIncrement 实际上不再是一个看起来像 { store.dispatch(...) } 的函数 - 它只是调度的动作 .

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

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

    我们最终会在按下按钮时执行适当的操作 .

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

    无论如何,只需在 onIncrement() 中添加大括号即可解决这个问题:

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

    您也可以只返回操作对象,如前所示 .

  • 1

    mapDispatchToProps() 已经在调度动作 . 添加 store.dispatch() 是多余的 .

    const mapDispatchToProps = {
      onIncrement: () => {
        return {
          type: 'INCREMENT'
        }
      },
      onDecrement: () => {
        return {
          type: 'DECREMENT'
        }
      },
    }
    
  • 4

    如果您正在使用mapDspatchToProps(),则不需要添加store.dspatch(),因为它已经隐含了 .

    const mapDispatchToProps  = {
      onIncrement: () => {
       return {
          type: 'INCREMENT'
        }},
    
      onDecrement: () => {
        return{
            type: 'DECREMENT'
        }},
    }
    

    干杯

相关问题