Redux优化
redux核心
store = createStore() 创建核心 store.getState() 获取数据 store.dispatch() 调用方法 store.subscribe 监听state数据,判断是否被修改
action creator
当redux变量增多,需要区分,首先修改case条件
高效的action
action types
将type定义为变量
combineReducer
actionType.js
export const persion_add = "persion/insert"
export const persion_delete = "persion/delete"
export const persion_update = "persion/update"
action.js
import {persion_add,persion_delete,persion_update} from './actionType'
export const persionAdd = data=>({type: persion_add,data})
export const persionDelete = index=>({type: persion_delete,index})
export const persionUpdate = (data,index)=>({type: persion_update,data,index})
reducer.js
import {persion_add,persion_delete,persion_update} from './actionType'
const init_list = [
{
id:3,
name: "张三",
age: 18
},
{
id:2,
name: "李四",
age: 18
},
{
id:1,
name: "王五",
age: 18
}
]
function personList(state = init_list,action){
switch (action.type){
case persion_add:
const obj = action.data
return [obj,...state]
case persion_delete:
state.splice(action.index,1)
return [...state]
case persion_update:
var index = action.index
state[index] = action.data
return [...state]
default:
return state
}
}
export default personList
index.js
import {createStore} from 'redux'
import personList from './PersionRedux/reducer'
const store = createStore(personList) //创建一个store对象
export default store
layout.jsx
import React, { Component } from 'react'
import store from '../redux'
import {persionDelete,persionUpdate,persionAdd} from '../redux/PersionRedux/action'
import { Table, Input,Form,Button } from 'antd';
import '../asserts/css/layout.css'
export default class Layout extends Component {
state = {
dataSource: [],
columns: [
{
title: '编号', //表头字段
dataIndex: 'id', //调用数据对应的字段 table.id
},
{
title: '姓名',
dataIndex: 'name',
},
{
title: '年龄',
dataIndex: 'age',
},
{
title: '操作',
render: (obj,a,index)=><>
<Button type="primary" success='true'
onClick={()=>this.edit(obj,index)}>修改</Button>
<Button type="primary" danger
onClick={()=>this.del(index)}>删除</Button>
</>
},
],
person_id: 0,
person_index: 0
}
UNSAFE_componentWillMount() {
store.subscribe(()=>{
this.setState({dataSource:store.getState()})
// setFieldsValue
this.form_ref.setFieldsValue(
{
name: "",
age: ""
}
)
this.setState({person_index: 0,person_id: 0})
})
this.setState({dataSource:store.getState()})
}
del(index){
store.dispatch(persionDelete(index))
}
edit(obj,index){
this.setState({person_index:index})
//设置form数据
this.form_ref.setFieldsValue(
{
name: obj.name,
age: obj.age,
}
)
this.setState({person_id: obj.id})
}
submit(value){
var id = this.state.dataSource.length>0?this.state.dataSource[0].id+1:1
var inserData = {
id,
name:value.name,
age: value.age
}
if(this.state.person_id){
inserData.id = this.state.person_id
store.dispatch(persionUpdate(inserData,this.state.person_index))
}else{
store.dispatch(persionAdd(inserData))
}
}
render() {
return (
<>
<div className="yangshi">
<Form
name="basic"
labelCol={
{ span: 8 }}
wrapperCol={
{ span: 16 }}
initialValues={
{ remember: true }}
autoComplete="off"
onFinish={this.submit.bind(this)}
ref={dom=>this.form_ref=dom}
>
<Form.Item
label="用户名"
name="name"
>
<Input />
</Form.Item>
<Form.Item
label="年龄"
name="age"
>
<Input />
</Form.Item>
<Form.Item wrapperCol={
{ offset: 8, span: 16 }}>
<Button type="primary" htmlType="submit">
保存
</Button>
</Form.Item>
</Form>
<Table
rowKey='id'
dataSource={this.state.dataSource}
columns={this.state.columns}
/>
</div>
</>
)
}
}
使用combineReducer
react-redux
1、redux比较复杂
2、直接使用redux,会在jsx的语法当中混入相当多的redux代码
react-redux是react的一个插件
作用: 帮助我们在react项目中更优雅的使用redux
安装
npm i react-redux -S
核心对象
react-redux式辅助开发者使用redux,而不是从新定义了redux,所以还需要借助之前的redux代码,整个思路就是将redux的数据和方法写到组件本身的component的props当中。
Provider
用法:将当前组件变为标签,包裹在react跟组件外部
作用:将store的数据传递给应用
connect
是一个由返回值的高阶函数
作用:获取Provider提供的数据,并将数据绑定到react组件的props当中。
connect拥有两个参数,分别代表: 1、绑定state数据的回调函数,函数自动接受来自Provider传递的state数据 2、绑定dispatch数据的回调函数,函数自动接受来自redux的dispatch方法,可以调用Provider传递action方法 二者都需要返回一个对象,对象当中的内容会被绑定组件的props上,
完整的layout代码
import React, { Component } from 'react'
import store from '../redux'
import {persionDelete,persionUpdate,persionAdd} from '../redux/PersionRedux/action'
import { Table, Input,Form,Button } from 'antd';
import '../asserts/css/layout.css'
import {connect} from 'react-redux'
class Layout extends Component {
state = {
dataSource: [],
columns: [
{
title: '编号', //表头字段
dataIndex: 'id', //调用数据对应的字段 table.id
},
{
title: '姓名',
dataIndex: 'name',
},
{
title: '年龄',
dataIndex: 'age',
},
{
title: '操作',
render: (obj,a,index)=><>
<Button type="primary" success='true'
onClick={()=>this.edit(obj,index)}>修改</Button>
<Button type="primary" danger
onClick={()=>this.del(index)}>删除</Button>
</>
},
],
person_id: 0,
person_index: 0
}
UNSAFE_componentWillMount() {
store.subscribe(()=>{
this.form_ref.setFieldsValue(
{
name: "",
age: ""
}
)
this.setState({person_index: 0,person_id: 0})
})
}
del(index){
this.props.persionDeleteAction(index)
}
edit(obj,index){
this.setState({person_index:index})
//设置form数据
this.form_ref.setFieldsValue(
{
name: obj.name,
age: obj.age,
}
)
this.setState({person_id: obj.id})
}
submit(value){
var id = this.props.persion_list.length>0?this.props.persion_list[0].id+1:1
var inserData = {
id,
name:value.name,
age: value.age
}
if(this.state.person_id){
inserData.id = this.state.person_id
this.props.persionUpdateAction(inserData,this.state.person_index)
}else{
this.props.persionAddAction(inserData)
}
}
render() {
return (
<>
<div className="yangshi">
<Form
name="basic"
labelCol={
{ span: 8 }}
wrapperCol={
{ span: 16 }}
initialValues={
{ remember: true }}
autoComplete="off"
onFinish={this.submit.bind(this)}
ref={dom=>this.form_ref=dom}
>
<Form.Item
label="用户名"
name="name"
>
<Input />
</Form.Item>
<Form.Item
label="年龄"
name="age"
>
<Input />
</Form.Item>
<Form.Item wrapperCol={
{ offset: 8, span: 16 }}>
<Button type="primary" htmlType="submit">
保存
</Button>
</Form.Item>
</Form>
<Table rowKey='id'
dataSource={this.props.persion_list}
columns={this.state.columns}
/>
</div>
</>
)
}
}
const mapStateToProps = (state)=>{
//connect内部调用的时候,会自动注入state对象,这个state对象数据来源Provider传参
return {
persion_list: state.persion
}
}
const mapDispathToProps = (dispatch)=>{
//在这里讲所有的action调用方法绑定props
return {
persionAddAction: (data)=>dispatch(persionAdd(data)),
persionDeleteAction: (id)=>dispatch(persionDelete(id)),
persionUpdateAction: (data,index)=>dispatch(persionUpdate(data,index))
}
}
export default connect(mapStateToProps,mapDispathToProps)(Layout)
汇总:
1、将昨天的redux/index.js拆分为 reducer.js 负责函数逻辑 action.js 负责脚本 actionType.js 负责定义操作类型 汇总到index.js当中 将汇总的数据通过provider传递到组件内部 在组件内部通过connect方法将数据和方法绑定到props上
bindActionCreators
selector
-
本质: 自定义方法, 对state中的数据进行处理
-
作用: 对数据进行筛选或者预处理
-
注意: selector函数必须有返回值
reselect
常规的selector过滤函数如果发生重复调用,会重复执行
官方并没有提供这样的功能,我们需要通过reselect来提出解决方案
安装
npm install reselect -S
核心方法
createSelector: 帮助我们创建selector函数, 并且会加入缓存机制
createSelector需要至少两个函数作为参数
-
第一个函数的作用是提供数据源, 第一个函数的返回值会自动注入最后一个处理函数中,(必须有返回值)
-
第二个函数的作用是进行最终的处理(必须有返回值)
import { createSelector } from "reselect"
//createSelector 把第一个函数的结果作为第二个函数的参数
export const getPersionList = createSelector(function (persion_list) {
return persion_list
}, function (data) {
return data.filter(item => {
if (item.age > 25) {
return true
}
return false
})
})
1、如何不让使用者修改开发者的代码
2、函数嵌套带来的惰性原理
function B(index){
//内存1T 数组 arrry
console.log("hello world")
return array[index]
}
B(100)
function A(index){
return function(){
//内存1T 数组 arrry
console.log("hello world")
return array[index]
}
}
A(100)()
3、生产消费者模式
redux调试工具
安装插件
npm i redux-devtools-extension -D
修改代码
redux-thunk
redux action 默认不可以支持异步的creater
redux-thunk是redux的一个中间件
可以支持异步actionCreator(在actionCreator方法中发送异步数据请求)
安装
npm i redux-thunk -S
注册中间件
import {
createStore,
combineReducers,
applyMiddleware
} from 'redux'
import personList from './PersionRedux/reducer'
import {composeWithDevTools} from 'redux-devtools-extension'
import thunk from 'redux-thunk'
// import goodsList from './GoodsRedux/reducer'
//combineReducers 可以合并多个reduser
const store = createStore(combineReducers({
persion: personList,
// goods:goodsList
}),composeWithDevTools(applyMiddleware(thunk))) //创建一个store对象
export default store