一.使用redux管理状态的常规案例:
1.创建基础功能
安装redux,react-redux
yarn add redux react-redux
创建仓库store
管理员reducer
组件中引入仓库
在子组件中进行链接
使用react-redux里的connect方法进行和父组件进行链接.
connect()方法里接收两个参数:mapStateToProps和mapDispathToProps
删除Header组件里的state,在reducer管理员手册里写状态
映射并使用
在管理手册中改为true,发现样式生效了.
同时,获焦和失焦的事件也不能是state来操作了
我们注释掉这两个方法和constructer
在this.获焦和失焦方法里也统一改为
在获焦方法里定义action对象,如:
回到reducer管理员这里操作改变数据
发现有效哦,同样方法失去焦点也这样写
最终的效果一致.
通过redux的引用,我们实现了将类里面的state放入到了仓库里进行管理,这样Header组件就变成了一个无状态的组件(无state,只有一个render函数,仓库的引用放在了App.js里),这样我们完全可以把它做成函数的形式(去掉里面的this),效果也是一样的,代码如下:
import React from 'react'
import {
HeaderWrapper,
Logo,
Nav,
NavItem,
NavSearch,
Addition,
Button,
SearchWrapper,
} from './style'
import { CSSTransition } from 'react-transition-group';
import {connect} from 'react-redux'
function Header(props) {
return (
<HeaderWrapper>
<Logo />
<Nav>
<NavItem className="left">首页</NavItem>
<NavItem className="left">下载App</NavItem>
<NavItem className="right login">登录</NavItem>
<NavItem className="right">
<span className="iconfont iconAa" />
</NavItem>
<SearchWrapper>
<CSSTransition
timeout={200}
in={props.focused}
classNames='slide'
>
<NavSearch
onFocus={props.handleInputFocus}
onBlur={props.handleInputBlur}
className={
props.focused?'focused':''
}/>
</CSSTransition>
<span className={props.focused?'focused iconfont iconai219 ':'iconfont iconai219 '} />
</SearchWrapper>
</Nav>
<Addition>
<span className="iconfont iconpan_icon" />
<Button className="writting">写文章</Button>
<Button className="reg">注册</Button>
</Addition>
</HeaderWrapper>
)
}
const mapStateToProps=(state)=>{
//state就是仓库里所有的数据
return {
focused: state.focused
}
}
const mapDispathToProps=(dispatch)=>{
return {
handleInputFocus(){
const action ={
type:'search_focus'
}
dispatch(action)
},//记得这里是逗号哦
handleInputBlur(){
// console.log(321);//发现有效
const action={
type:'search_blur',
}
dispatch(action)
}
}
}
// 记住connect方法是下面这样写的
export default connect(mapStateToProps,mapDispathToProps)(Header)
二.简化reducer(进行分类,分为大小reducer)
reducer就相当于图书管理员的图书手册,如果我们把很多数据都写在reducer是不合理的,现在开始把reducer分为不同的reducer(相当将图书进行分类)
我们在header里创建reducer分类,将本来属于header组件的所有reducer代码剪切过来
在大的reducer里重新写
工具:发现focus已经在header组件下面了.
回到子组件js文件里,因为reducer已经多了一层header,所以对应的state也应该加上一层header.操作如下:
最终的效果还是一样.
无关紧要的文件名导入太长小技巧:
小reducer
大reducer
这样实现的效果也是一样的.
三.action的拆分
采用actionCreators来代替常量创建的方式,里面写代码如下:
回到header组件里进行引用和使用
在actionCreators.js文件里的type类型我们继续做优化
先创建一个constants.js(常量),在里面写如下代码
在actionCreators.js里导入并修改type类型
在小的reducer里也进行导入并修改type
继续优化我们的header组件里的store文件夹,使他默认都导入index.js文件而不用导入store文件夹里的很多其他文件呢
在header/store/index.js里
这样在header/index.js里,可以不用写那么多路径
这样效果还是不会变的.
总结:我们实现了一个完美的组件分工
四.安装immutable让子reducer管理员里的state状态不可改变
安装immutable
yarn add immutable
引入并转化成immutable对象
回到子组件里进行使用
同时,返回的也要是immutable对象写法
immutable对象的set方法原理是:结合之前immutable对象的值和设置的值进行比较,最后返回一个全新的对象,老的对象并没有去改.
这样效果还是一致.
五.安装redux-immutable使子组件header里的focused: state.header也变为immutable对象
安装
yarn add redux-immutable
这里的state.header是在父reducer管理员生成的,所以回到大的reducer里,修改如下代码
回到子管理员reducer里,返回值也写成immutable对象
在子组件header中修改state即可
最终的效果还是一样没变.