react react-redux数据共享
- 1.目的
- 2.数据共享版本
- 2.1Person模块的添加
- 2.1.1 Containers下的Person
- 2.1.2 actions下的person.js
- 2.1.3 reducers下的person.js
- 2.2 store.js的改写!
- 2.3 组件中取出状态的时候,记得“取到位”
- 3.纯函数
1.目的
前面的react和react-redux的使用也只是一个容器组件+一个UI组件和redux进行交互,实际上并没有实现数据共享的目的,没有其他的容器组件+UI组件来进行共享.最终实现的小效果:
2.数据共享版本
文件目录结构:
2.1Person模块的添加
2.1.1 Containers下的Person
import React, { Component } from 'react'
import {nanoid} from 'nanoid'
import {connect} from 'react-redux'
import {createAddPersonAction} from '../../redux/actions/person'
class Person extends Component {
addPerson = ()=>{
const name = this.nameNode.value
const age = this.ageNode.value
const personObj = {id:nanoid(),name,age}
this.props.jiaYiRen(personObj)
this.nameNode.value = ''
this.ageNode.value = ''
}
render() {
return (
<div>
<h2>我是Person组件,上方组件求和为{this.props.he}</h2>
<input ref={c=>this.nameNode = c} type="text" placeholder="输入名字"/>
<input ref={c=>this.ageNode = c} type="text" placeholder="输入年龄"/>
<button onClick={this.addPerson}>添加</button>
<ul>
{
this.props.yiduiren.map((p)=>{
return <li key={p.id}>{p.name}--{p.age}</li>
})
}
</ul>
</div>
)
}
}
export default connect(
state => ({yiduiren:state.peoples,he:state.he}),//映射状态
{jiaYiRen:createAddPersonAction}//映射操作状态的方法
)(Person)
2.1.2 actions下的person.js
import {ADD_PERSON} from '../constant'
//创建增加一个人的action动作对象
export const createAddPersonAction = personObj => ({type:ADD_PERSON,data:personObj})
2.1.3 reducers下的person.js
import {ADD_PERSON} from '../constant'
//初始化人的列表
const initState = [{id:'001',name:'tom',age:18}]
export default function personReducer(preState=initState,action){
// console.log('personReducer@#@#@#');
const {type,data} = action
switch (type) {
case ADD_PERSON: //若是添加一个人
return [data,...preState]
default:
return preState
}
}
2.2 store.js的改写!
/*
该文件专门用于暴露一个store对象,整个应用只有一个store对象
*/
//引入createStore,专门用于创建redux中最为核心的store对象
import {createStore,applyMiddleware,combineReducers} from 'redux'
//引入为Count组件服务的reducer
import countReducer from './reducers/count'
//引入为Person组件服务的reducer
import personReducer from './reducers/person'
//引入redux-thunk,用于支持异步action
import thunk from 'redux-thunk'
//汇总所有的reducer变为一个总的reducer
const allReducer = combineReducers({
he:countReducer,
peoples:personReducer
})
//暴露store
export default createStore(allReducer,applyMiddleware(thunk))
这里也是重点,最后注意
2.3 组件中取出状态的时候,记得“取到位”
根据store.js中定义暴露的就行对应
3.纯函数
将reducers下的person.js文件代码改变一下:
import { ADD_PERSON } from '../constant'
//初始化人的列表
const initState = [{ id: '001', name: 'tom', age: 18 }]
export default function personReducer(preState = initState, action) {
// console.log('personReducer@#@#@#');
const { type, data } = action
switch (type) {
case ADD_PERSON: //若是添加一个人
console.log('动辄来了')
preState.unshift(data)
console.log(preState)
return preState
// return [data,...preState]
default:
return preState
}
}
看着完全没有毛病的,只是换了一种写法嘛,但是问题就来了!!!
根据控制台看得出是执行了方法了的,但是页面没有反映出来。为什么呢
参考:添加链接描述
通过源代码,我们发现,var nextStateForKey = reducer(previousStateForKey, action), nextStateForKey就是通过 reducer 执行后返回的结果(state),然后通过hasChanged = hasChanged || nextStateForKey !== previousStateForKey来比较新旧两个对象是否一致,此比较法,比较的是两个对象的存储位置,也就是浅比较法,所以,当我们 reducer 直接返回旧的 state 对象时,Redux 认为没有任何改变,从而导致页面没有更新。
所以react也规定reducer必须是纯函数,纯函数我理解的就是:
1.参数相同,输出结果相同
2.不能对参数再进行赋值改变
3.不能出现Math.random(),Data.now()之类的产生不确定因素的结果的方法
4.不能调用异步接口,也会受网络等影响导致结果不一致