Redux
一、redux的基本配置
- 下载redux的依赖包
- 基本redux入口文件创建和配置
由于redux不像vuex,我们必须包括文件的创建,基本入口文件都是需要自己创建
1)在src创建一个名称为redux或者store文件
2)在store文件夹下创建入口文件index.js
import {legacy_createStore as creatStore} from 'redux'
// 通过createStore来创建仓库
// store仓库中的state(状态)的初始化是通过给createState()方法的设置参数来完成的
// 他的参数是一个回调函数
// 这个回调函数的返回值就是将初始值num,存储到store的state中
// 这个createStore函数的返回值就是store对象了
const store = creatStore((num=10)=>{
return num
})
// 由于别的地方要调用store对象,需要将该对象导出
export default store
二、Redux工作流程
- 编写组件
- 对redux进行基本配置
- 在src目录下创建store文件夹,在该文件中编写基本配置
import {legacy_createStore as creatStore} from 'redux'
//编写reduce
const counterReduce=(state=0,action)=>{
Switch(action.type){
case 'addition':
return state+1
case 'substraction':
return state-1
default :
return state
}
}
const store = creatStore(counterReduce)
export default store
- 完成对reduecr的配置
- 组件中使用redux
- 在组件中通过store.dipatch(action对象)向store仓库发送动作,根据具体的动作完成对仓库reduce的调用,在完成具体仓库中state数据的变化。
- 组件中检测到数据的变化
store对象中有一个方法,subscribe()
import store from './store'
export default Counter(){
useEffect(()=>{
store.subscribe(()=>{
store.getState()
setNum({})
})
},[])
const [num,setNum] = useState(0)
// 在redux的store对象中提供了一个方法dispatch()
// 他的参数是一个action对象,该对象必须要有一个type属性,该属性是操作的动作
const increment = ()=>{
store.dispatch({
type:'addition'
})
}
const decreas = ()=>{
store.dispatch({
type:'substraction'
})
}
return (
<div>
{store.getState()}
<button onClick={()=>{increment()}}>+</button>
<button onClick={()=>{decreas()}}>-</button>
</div>
)
}
三、Redux的写法优化
可以有如下方式优化
action的优化
1. action creator
action creator实际上是一个函数,该函数主要的作用是用来创建action对象,具体做法如下
- 在src/store目录下创建action的目录,该目录主要存放的是action相关的js文件
export function additionActionCreator(num){
return {
type:'addition',
num:num
}
}
// 减法,这里使用的是ES6简写来写减法
export const substractionActionCreator = num=>({type:'substraction',num})
2.action对象的type变量化
export const ADDITION = 'addition'
export const SUBSTRACTION = 'substraction'
reducer优化
从两个方面优化:
- 将reducer的计算处理函数从store入口文件中提取出来作为模块专门进行管理
- reducer的state初始化的时候,不建议直接赋基本数据类型的量,这样会对state进行污染,可以直接定义一个对象,把所要共享的数据作为state对象中一个成员(属性)来存在
- 创建counterReduce.js文件
import {ActionType的变量} from '../'
const counterReducer = (state={
count:10
},action){
Switch(action.type){
case Type的变量名:
return {...state,count:state.count+action.num}
default:
return state
}
}
export default counterReducer
react-redux概述
依赖包的安装
由于react-redux是基于redux的,所以安装的时候必须先安装redux依赖包,而后在安装react-redux依赖包
npm i redux
npm i react-redux
2、redux的基本配置
- store的入口文件的配置
import {legacy_createStore as creatStore} from 'redux'
import counterReduce from '@/store/reduc/counterReduce'
const store = creatStore(counterReduce)
export default store
- 编写action creator
export function additionActionCreator(num){
return {
type:'addition',
num:num
}
}
// 减法,这里使用的是ES6简写来写减法
export const substractionActionCreator = num=>({type:'substraction',num})
- 编写reudcer
import {ActionType的变量} from '../'
const counterReducer = (state={
count:10
},action){
Switch(action.type){
case Type的变量名:
return {...state,count:state.count+action.num}
default:
return state
}
}
export default counterReducer
3、全局注入store仓库
在src/index.js整个项目的入口文件
,使用react-redux提供的组件Provider将App根组件包裹起来
在Provider组件标签中使用store属性,将自定义的store对象引入
import {Provider} from 'react-redux'
import ReactDOM from "react-dom/client";
import App from "./App.js";
import React from "react";
import {BrowserRouter} from 'react-router-dom'
const root = ReactDOM.createRoot(document.querySelector('#root'))
root.render(
<BrowserRouter>
< Provider store={store}>
<App></App>
</ Provider>
</BrowserRouter>
)
4、组件中使用react-redux
在react-redux中提供了一个高阶组件,这个高阶组件connect
- 首先从react-redux库中导入connect,可以将我们的函数组件封装起来,封装之后,就可以访问和操作state的内容
import {connect} from 'react-redux'
function Counter(props){
// props就会有dispatch和state内的状态
const mapStateToProps =(state)=>{
return state
}
return (
<div>{props.count}</div>
)
}
export default connect(mapStateToProps)(Counter)
react-redux hook方式
步骤:
- 创建store文件夹,里面分别有index.js的入口文件,action creator文件,reducer文件
index入口文件
import {legacy_createStore} from 'redux'
const store = createStore()
export default store
action文件
- counterAction.js
import {ADDITION,SUBSTRACTION} from 'action文件地址'
export const addition = num=>({type:ADDITION,num})
export const substraction = num=>({type:SUBSTRACTION,num})
- actionTypes.js
export const ADDITION = 'addition'
export const SUBSTRACTION = 'substraction'
reducer文件
import {ADDITION,SUBSTRACTION} from 'action变量文件地址'
const counterReducer = (state={count:0},action)=>{
Switch(action.type){
case ADDITION:
return {...state,count:action.num+state.count}
default:
return state
}
}
export default counterReducer
index.js文件
import {legacy_createStore as createStore} from 'redux'
// 导入reducer文件
import counterReducer from './reducer文件地址'
const store = createStore(counterReducer)
export default store
全局注入store
实际上使用的是react-redux的connect高阶组件
import React from 'react'
import ReactDOM from 'react-dom/client'
import {Provider} from 'react-redux'
import store from './仓库的入口文件'
const root = ReactDom.createRoot(document.querySelector('#root'))
root.render(
<Provider store={store}>
<App></App>
</Provider>
)
页面操作state
import React from 'react'
// 导入useSelectorm,useSelector实际上是一个回调函数
import {useSelector,useDispatch} from 'react-redux'
import {addition} from 'action文件地址'
export default function Counter(props){
const num = useSelector((state)=>{
return state.count
})
const dispatch = useDispatch()
const increment = ()=>{
dispatch(addition(3))
// 或者传入外界传进来的props
dispatch(addition(props.m))
}
return (
<div>
Counter
{num}
<button onClick={increment}>+</button>
</div>
)
}