上节课我们已经完成了大致的一个流程,我们有了action
,有了reducer
,也把我们onClick
事件的回调获得的值也封装成了一个对象,而且还通过nanoid
来为每个对象生成了一个独有的id
,那么接下来我们就把整个流程给实现吧。
回顾
上节课没有什么新的知识点,就一个默认参数的传递,我们就不多做赘述了,我们开始这节课的内容。
组件展示实现
我们现在整套流程已经架起来了,但是我们还没有实现,那么我们现在Person
组件中来展示一下我们的效果,看看自身能不能拿到redux
中的state
。
但是我现在要说一个问题,我们现在虽然有了action
和reducer
,但是实际上来说,我们这个reducer
根本没有执行,我们来验证一下,在两个组件的reducer
中分别打印组件名来看一下效果:
大家看,控制台中只输出了sum
,是不是代表着Sum
组件的reducer
被成功执行了?但是没有输入person
,那么这是怎么回事儿呢?我们的reducer
是不是由store
来控制调度的?那么我们来到store
里面来看一眼:
import { createStore,applyMiddleware } from 'redux'; import sumReducer from './reducers/sum'; import thunk from 'redux-thunk'; export default createStore(sumReducer,applyMiddleware(thunk));
大家有没有发现问题所在?第一我们没有导入person
的reducer
,其次我们在最后一行创建store
的时候,是不是把sumReducer
传进去了?但是我们传person
的reducer
了吗?是不是没有?所以说person
的reducer
并没有被执行,那么我们怎么来改一下呢?
import { createStore, applyMiddleware, combineReducers } from 'redux'; import sumReducer from './reducers/sum'; import personReducer from './reducers/person'; import thunk from 'redux-thunk'; const allReducers = combineReducers({ sum: sumReducer, person: personReducer }) export default createStore(allReducers, applyMiddleware(thunk));
我们来看一下代码,我们导入了personReducer
,那么我们怎么传到createStore
函数里呢?我们之前可没有说createStore
可以多个 reducer
一直连续往里传,所以说我们要借助一个API
叫combineReducers
,这个API
接收一个对象。
接下来我要讲一个很重要的点:combineReducers API
接收到的对象就redux
最终的状态的对象。
什么意思呢?我们之前还没有写Person
组件的时候我们redux
组件里面的state
存的是什么?是不是就是一个数字?Sum
组件要用的时候直接调用getState
方法然后直接就获取到了这个数字。那么现在我们有了一个Person
组件。这个组件也要往redux
里面存数据,存了一个数组,那么这个state
是不是就乱了啊?我们取数据如果getState
的话,我们获取到的数据是什么呢?不知道是什么啊,所以说大家觉得redux
中的state
如果是一个对象的话,我们在存取数据的时候是不是就很方便了?
而combineReducers API
所接收到的这个对象,就是redux
中的state
对象。那么我们以后getState
方法获取到的数据是不是就是一个对象,而不再是一个数字或者数组了。
那么我们来让Person
组件上先来展示一下我们的输入信息:
export default class Person extends Component { componentDidMount() { store.subscribe(()=>this.setState({})) } render() { return ( <div> <input ref={c => this.name = c} type="text" placeholder="input name" /> <input ref={c => this.age = c} type="text" placeholder="input age" /> <button onClick={this.addPerson}>submit</button> <div> { store.getState().person.map(p=><li id={p.id}>name: {p.name}, aeg: {p.age}</li>) } </div> <h2>当前求和为:{store.getState().sum}</h2> </div> ) } addPerson = () => { const name = this.name.value; const age = this.age.value; const person = { id: nanoid(), name, age } store.dispatch(createAddPersonAction(person)); } }
我们来看一下代码,我们目前还没有写容器组件,所以说是直接操作的redux
,那么我们是不是要用store
来dispatch
?然后我们在展示的时候要从getState
获取到的对象中取到person
属性。那么我们把Sum
组件的数据也拿过来吧。而且我们是不是直接操作的redux
?那么我们是不是要手动监测redux
的state
更新?现在我们再看一下页面:
这一下是不是跑通了?那么接下来我们来把他改回UI
组件,然后来创建容器组件吧。
class Person extends Component { render() { return ( <div> <input ref={c => this.name = c} type="text" placeholder="input name" /> <input ref={c => this.age = c} type="text" placeholder="input age" /> <button onClick={this.addPerson}>submit</button> <h2>当前求和为:{this.props.sum}</h2> </div> ) } addPerson = () => { const name = this.name.value; const age = this.age.value; const person = { id: nanoid(), name, age } this.props.add(person); } } export default connect( state => ({sum: state.sum}), { add: createAddPersonAction } )(Person)
我们来看一下代码,我们取消对UI
组件的暴露,对外默认暴露容器组件,我们说了connect
要在第一次调用的时候传入另个参数:
- 状态数据
- 操作状态的方法
那么我们是不是要在Person
组件中展示Sum
组件的数据,使用我们就传入sum
,顺便我们也改一下Sum
组件中的展示吧:
class Sum extends Component { render() { return ( <div> <select ref={c => this.selectNum = c}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> </select> <button onClick={this.add}>+</button> <button onClick={this.dec}>-</button> <button onClick={this.odd}>odd</button> <button onClick={this.async}>async</button> <ul> { this.props.person.map(p=><li id={p.id}>name: {p.name}, age: {p.age}</li>) } </ul> </div> ) } add = () => { const { value } = this.selectNum; this.props.increment(value * 1) } dec = () => { const { value } = this.selectNum; this.props.decrement(value * 1) } odd = () => { const { value } = this.selectNum; if (this.props.sum % 2 !== 0) this.props.increment(value * 1) } async = () => { const { value } = this.selectNum; this.props.asyncIncrement(value * 1, 500); } } export default connect( state => state, { increment: createIncrementAction, decrement: createDecrementAction, asyncIncrement: createAsyncIncrementAction } )(Sum);
代码我就不多赘述了,我们单讲一下,我们的取数,为什么我们直接把satte
里面这两个数据都拿了啊?因为我们有一个要判断奇数的操作。那么我们整体看一下效果吧:
这一下,我们的所有功能更久都实现了。现在我们的共享数据就已经完成了
总结
combineReducers
函数整合reducer
combineReducers
中接收一个参数是对象combineReducers
接收到的对象就是redux
中的状态对象
Copyright statement:The articles of this site are all original if there is no special explanation, indicate the source please when you reprint.
Link of this article:https://work.lynchow.com/article/finish_share_data/