问题描述
您收到重复调度的原因是您编写 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 示例动作触发两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!