【发布时间】:2018-05-31 03:29:32
【问题描述】:
我很难理解应该如何使用我的 react 组件中的操作来分派全局商店。我对整个概念很陌生,我没有让我的组件在 dispatch() 上重新渲染。我投入很大,发现虽然 reducer 返回更新后的全局状态,但值并没有映射回组件 props。但是定义了一个适当的函数(mapStateToProps)。
最小示例:Please have a look at this plunkr(或下面的最小示例代码)。
说明:
我有一个组件Controls 和一个方法switchActivities。该组件已连接到全局存储,并且我的全局状态在组件道具中可用。
var PullFromStoreControls = function (state) {
return {
concrete: state.me.bool,
nested: state.me.nested.later
}
}
var PushToStoreControls = function (dispatch) {
return {
switchFilter: function (type, value) {
dispatch({
type: 'SET_VAL',
value: value
})
}
}
}
Controls = connect(
PullFromStoreControls,
PushToStoreControls
)(Controls)
我将变量 state.me.bool 连接到 props.conrete 以避免深度状态树的副作用。我还连接了一个调度程序以通过减速器更新全局状态。但是,如果调度程序由'switchActivities'调用,则复选框的新值使其正确地传递给reducer,然后丢失。全局状态似乎从未正确更新。
我错过了什么?
index.html
<!DOCTYPE html>
<html>
<head>
<script data-require="react@*" data-semver="15.5.0" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.5.0/react.min.js"></script>
<script data-require="react@*" data-semver="15.5.0" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.5.0/react-dom.min.js"></script>
<script data-require="redux@*" data-semver="3.2.1" src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.2.1/redux.js"></script>
<script data-require="react-redux@*" data-semver="4.4.5" src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/4.4.5/react-redux.js"></script>
<!-- support for jsx on my localhost, on Plunkr jsx will be automatically transpiled to js -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type = "text/babel" src="minimal.jsx"></script>
</head>
<body>
<div id="app"></div>
</body>
</html>
minimal.jsx
function d(x){
console.log(x);
}
const AppState = {
me: {
bool: false,
nested: {
later: "I also want to change values deeper in the tree."
}
}
}
function reducer(state, action) {
if (state === undefined) {
return AppState;
}
switch (action.type) {
case 'SET_VAL':
state.me.bool = action.value;
break;
}
console.log("The reducer returns the changed state");
console.log(state);
return state;
}
// create global store with initial configuration `AppState`
const store = Redux.createStore(reducer, AppState);
// create provider and connect function not having webpack available
var Provider = ReactRedux.Provider;
var connect = ReactRedux.connect;
class Controls extends React.Component {
switchActivities() {
console.log("------------------ clicked ------------------");
console.log("set value from:");
console.log(this.props.concrete);
// inverse current state
const state = !this.props.concrete;
// output
console.log("to:");
console.log(state);
// call dispatcher
this.props.switchFilter("show_act", state);
}
render() {
console.log("I would like to re-render if this.props.concrete has updated!");
const switchActivities = <MapSwitch name="switch_act" label="Show something" checked={this.props.concrete} onChange = {() => this.switchActivities()} />;
return <div id="map-controls">
{switchActivities}
</div>
}
}
var PullFromStoreControls = function (state) {
return {
concrete: state.me.bool,
nested: state.me.nested.later
}
}
var PushToStoreControls = function (dispatch) {
return {
switchFilter: function (type, value) {
dispatch({
type: 'SET_VAL',
value: value
})
}
}
}
Controls = connect(PullFromStoreControls, PushToStoreControls)(Controls)
const MapSwitch = ({name, label, checked, onChange}) => (
<label for={name}>{label}
<input type="checkbox" className="switch" data-toggle="switch"
name={name}
onChange={onChange}
checked={checked}
/>
</label>
)
ReactDOM.render(
<Provider store={store}>
<Controls/>
</Provider>,
document.getElementById('app')
);
解决方案(更新)
我在 reducer 中更改 state 对象并返回它,或者我创建一个新对象并返回它,这是不同的。尽管两个返回的对象都是相同的,但前者是一个引用,而后者是一个真正的新变量。我很难学到这一点。
很好的解释: https://github.com/reactjs/redux/blob/master/docs/recipes/reducers/ImmutableUpdatePatterns.md
function reducer(state, action) {
switch (action.type) {
case 'SET_VAL':
return {
...state,
me : {
...state.me,
bool: action.value
}
}
}
return state;
}
【问题讨论】:
标签: javascript reactjs redux react-redux jsx