一、 Redux三大核心理念★★★
- Store :定义数据state 只读
- action :通过action来更新数据
- reducer: 纯函数来执行修改
1.1 什么是 Redux Toolkit? ★★★
- 官方推荐的编写 Redux 逻辑的方法。
@reduxjs/toolkit包封装了核心的redux包,包含我们认为构建 Redux 应用所必须的 API 方法和常用依赖。 Redux Toolkit 集成了我们建议的最佳实践,简化了大部分 Redux 任务,阻止了常见错误,并让编写 Redux 应用程序变得更容易 - 要写任何的 Redux 逻辑,你都应该使用 Redux Toolkit 来编写代码
- 创建 Redux Toolkit 来消除手写 Redux 逻辑中的「样板代码」,防止常见错误,并提供简化标准 Redux 任务的 API
- 创建 Redux Toolkit 来消除手写 Redux 逻辑中的「样板代码」,防止常见错误,并提供简化标准 Redux 任务的 API
1.2 redux基本使用
- 使用
npm install redux安装redux
简单基本示例使用
Eg:
//store.js // 进行引入 const { createStore } = require("redux") // 定义初始化数据 const initState = { name: "林夕", age: 18 } // 定义reducer函数:纯函数 function reducer(state = initState, action) { // 参数state:store目前保存的state // 参数action:本次次需要更新Waction(dispatchi入iaction) // console.log(state, action); // 有数据更新进行更新,返回新state switch (action.type) { case "name_change": return { ...state, name: action.name } case "age_change": return { ...state, age: action.age } default: return state; } // 返回值就是本次存储的initState值:即store值 return state } // 创建store const store = createStore(reducer) module.exports = store//使用 const store = require("./store"); console.log(store.getState()); // 修改store中的数据:必须action const nameAction = { type: 'name_change', name: 'Go to swimming pool' } store.dispatch(nameAction) console.log(store.getState()); const ageAction = { type: 'age_change', age: 22 } store.dispatch(ageAction) console.log(store.getState());
逐步优化代码,监听订阅修改使用subscribe
1.3 subscribe(listener)监听数据是否变化
变化监听器。每当 dispatch action 的时候就会执行,state 树中的一部分可能已经变化。你可以在回调函数里调用 getState() 来拿到当前 state
1.3.1 参数
listener(Function): 每当 dispatch action 的时候都会执行的回调。state 树中的一部分可能已经变化。你可以在回调函数里调用getState()来拿到当前 state。store 的 reducer 应该是纯函数,因此你可能需要对 state 树中的引用做深度比较来确定它的值是否有变化。
1.3.2返回值
(Function): 一个可以解绑变化监听器的函数。
const store = require("./store");
// 定义动态生成action可以新建新文件---始
//这里的type名字同样可以进行抽取使用。
const nameActionDispatch = (name) => ({ type: "name_change", name })
const ageActionDispatch = (age) => ({ type: "age_change", age })
// 定义动态生成action可以新建新文件---末
//订阅监听
const unsubscribe = store.subscribe(() => {
console.log("监听修改", store.getState());
})
// 修改store中的数据:必须action
store.dispatch(nameActionDispatch("Go to swimming pool"))
store.dispatch(ageActionDispatch(22))
//取消订阅监听
unsubscribe()
store.dispatch(nameActionDispatch("取消订阅"))
- 其上代码我们可以进行拆分逻辑抽取单独文件进行优化,做到编写一次复用N次进行优化。
- 同时遵从三大核心理念进行拆分文件,有需要可以拆分一个常量文件用来导出type名;
tips
- 注意:node中对ES6模块化的支持
- 从node v13.2.0开始,node才对ES6模块化提供了支持
- node v13.2.0之前,需要进行如下操作:
- 在package.json中添加属性:"type":"module”;
- 在执行命令中添加如下选项:node --experimental-modules src/index.js;
- node v13.2.0之后,只需要进行如下操作:在package.json中添加属性:"type":"module”;
- 注意:导入文件时,需要跟上.js后缀名:
二、 react中初次使用redux实例练习
- 使用
create-react-app '项目名'创建项目 - 使用
npm install redux安装redux
示例效果
新建目录
APP.jsx文件
import React, { PureComponent } from 'react'
import Home from './peages/Home'
import User from './peages/User'
import { HOC } from './utils/higherOrderComponent'
const Homes = HOC(Home)
const Users = HOC(User)
// 这里懒得拆分单文件了,使用函数创建了一个组件
const Header = HOC((props)=>{
return(<h2>我是APP组件:{props.count}</h2>)
})
export class App extends PureComponent {
render() {
return (
<>
<Header/>
<Homes />
<div>
<Users />
</div>
</>
)
}
}
export default App
Home.jsx文件子组件
import React, { PureComponent } from 'react'
import store from '../store'
import { addNumAction } from '../store/actionCreators'
export class Home extends PureComponent {
add(num){
store.dispatch(addNumAction(num))
}
render() {
//高阶组件进行拦截后的传输参数
const { count } = this.props
return (
<>
我是home增加计数:{ count }
<div>
<button onClick={e=>this.add(1)}>+1</button>
<button onClick={e=>this.add(5)}>+5</button>
<button onClick={e=>this.add(10)}>+10</button>
</div>
</>
)
}
}
export default Home
User.jsx文件子组件
import React, { PureComponent } from 'react'
import store from '../store'
import { reduceNumAction } from '../store/actionCreators'
export class User extends PureComponent {
reduceClick(num) {
store.dispatch(reduceNumAction(num))
}
render() {
//高阶组件进行拦截后的传输参数
const { count } = this.props
return (
<>
我是User减少计数:{count}
<div>
<button onClick={e => this.reduceClick(1)}>-1</button>
<button onClick={e => this.reduceClick(5)}>-5</button>
<button onClick={e => this.reduceClick(10)}>-10</button>
</div>
</>
)
}
}
export default User
higherOrderComponent.js高阶组件不明白高阶组件的使用请移步React的高阶组件
import {PureComponent} from 'react'
import store from '../store'
// 这里封装了一个高阶组件,相当进行拦截操作。
export function HOC(WrappedComponent){
class NewWrappedComponent extends PureComponent{
constructor() {
super()
this.state = {
count:store.getState().counter
}
}
componentDidMount() {
store.subscribe(() => {
const state = store.getState()
//实现更新因为这里高阶组件使用setState数据变化都会进行更新界面
this.setState({count:state.counter})
})
}
render(){
return(
<>
<WrappedComponent {...this.props} {...this.state}/>
</>
)
}
}
return NewWrappedComponent
}
2.1 redux结构划分
源自coderwhy学习
store/index.js入口文件
import { createStore } from 'redux'
import reducer from './reducer'
const store = createStore(reducer)
export default store
reducer.js 纯函数来执行修改state
import { ADD_COUNTER, REDUCE_COUNTER } from './constants'
const initState = {
counter: 10
}
function reducer(state = initState, action) {
switch (action.type) {
case ADD_COUNTER:
let counter = state.counter + action.counter
return { ...state, counter }
case REDUCE_COUNTER:
let reduceCounter = state.counter - action.counter
return { ...state, counter: reduceCounter }
default:
return state;
}
}
export default reducer
actionCreators.js执行action函数抽取单文件
import { ADD_COUNTER,REDUCE_COUNTER } from './constants'
export const addNumAction = (counter) => ({ type: ADD_COUNTER, counter })
export const reduceNumAction = (counter) => ({ type: REDUCE_COUNTER, counter })
constants.js 用来存储改type
export const ADD_COUNTER = "add_counter"
export const REDUCE_COUNTER = "reduce_counter"
连接下文
未完待续。。。