input调用changeName是好的,可是这个button调用access就有问题了,其实计数器是增加了,但是没有触发render()方法
import React, { Component } from 'react';
import { render } from 'react-dom';
import { createStore, bindActionCreators } from 'redux';
import { Provider, connect } from 'react-redux';
const reducer = (state = {
name: '',
num: 0,
}, action) => {
const { type, payload = {} } = action;
switch (type) {
case 'changeName':
return {
name: payload.name,
num: state.num,
};
case 'access':
return {
name: state.name,
num: ++state.num,
};
default:
return state;
}
};
const store = createStore(reducer);
let actions = {
changeName(name) {
return {
type: 'changeName',
payload: {
name,
},
};
},
access() {
return {
type: 'access',
};
},
};
actions = bindActionCreators(actions, store.dispatch);
// ===================
class UI extends Component {
render() {
const { name, num, access, changeName } = this.props;
return (<div>
<h1>名字: {name}</h1>
<h2>计数器: {num}</h2>
<input type="text"
onChange={(eve) => changeName(eve.target.value.trim())}/>
<button onClick={() => access()}>计数器增加</button>
</div>);
}
};
const UI2 = connect(state => state, () => actions)(UI);
render(
<Provider store={store}>
<UI2/>
</Provider>
,
document.getElementById('app'));
state.num + 1
不要++state.num
在 Redux 的官方文档中有这么一段话:
意思就是 reducer 必须是一个纯函数,所谓的纯函数,就是:不要在函数内修改参数,不要进行 API 调用,路由切换等有副作用的操作,不要调用非纯函数,只进行计算;纯函数给相同的输入,永远都会有相同的输出。
render 的工作就是计算生成一个新的 state,而不是修改原来的那个 state。
回到你这个问题:
你这里这个 reducer 就不是纯函数,因为
++state.num
修改了参数 state。Redux 只有检测到 state 发生变化才会触发订阅的回调函数,也就是说 react-redux 才会重新渲染。
你先把原来的 state.num 加 1,然后返回的新的 state 也是加 1 后的,Redux 将两个 state 进行比对就会发现没有发生任何变化。其实是你成功骗过了 redux。