redux是什么
-
redux
是一个专门用于做状态管理的JS库(不是react插件库)。 -
它可以用在
react
,angular
,vue
等项目中, 但基本与react
配合使用。 -
作用: 集中式管理
react
应用中多个组件共享的状态。
使用场景
-
某个组件的状态,需要让其他组件可以随时拿到(共享)。
-
一个组件需要改变另一个组件的状态(通信)。
-
总体原则:能不用就不用, 如果不用比较吃力才考虑使用。
redux工作流程
redux的三个核心概念
action
响应用户动作的对象, 也可也是异步的action
直接发起用户请求
包含2个属性: type
:标识属性, 值为字符串, 唯一, 必要属性; data
:数据属性, 值类型任意, 可选属性。
eg:
{ type: 'ADD_STUDENT',data:{name: 'tom',age:18} }
reducers
用于初始化状态、加工状态。
加工时,根据旧的previousState
和action
, 产生新的state
的纯函数。
let data = []
const todoReduce = function( preState=data, action ) {
let { type, data } = action
switch (type) {
case "todo_add":
preState.push({ name: "法外狂徒张三" })
return preState
default:
return preState
}
}
export default todoReduce
store
将state
、action
、reducers
联系在一起的对象
// 如何得到此对象?
import {createStore} from 'redux'
// 引入 reducers
import reducer from './reducers'
// 创建对象
const store = createStore(reducer)
// 将store对象暴露 并在index.js 中引入js进行使用
export default store此对象的功能?
1) getState(): 得到 state 数据仓库中的数据
2) dispatch(action): 分发action, 触发reducer调用, 产生新的state
3) subscribe(listener): 注册监听, 当产生了新的state时, 自动调用
redux的核心API
createstore()
作用:创建包含指定reducer的store对象
store对象
作用: redux
库最核心的管理对象; 它内部维护着: state
,reducer
。
核心方法:
-
getState() -- 获取仓库数据
-
dispatch(action) -- 派发动作 触发
action
-
subscribe(listener) -- 监听数据的变化触发页面的渲染(只能浅层次监听数据的变化)
eg:
-
store.getState()
-
store.dispatch({type:'INCREMENT', data: number})
-
注意: 这种写法直接略过action,调用
reducers
, 数据在reducers
第二的参数可以拿到; -
注意:
reducers
只能接收对象参数, 想要实现异步请求action
需要thunk
插件的帮助
-
-
store.subscribe(render)
store.getState() // 页面获取store中存储的数据
store.dispatch() // 派发一个事件
store.dispatch({
type:"add",
data:0
})
store.subscribe(()=>{}) // 监听仓库变化,变化就会触发
applyMiddleware()
作用:应用上基于redux的中间件(插件库)
combineReducers()
作用:合并多个reducer
函数
参考案例
基本使用
安装redux依赖库,版本可以不用管: 安装后查看一下根目录的package.json文件是否安装上
cnpm i redux -- save
接下来我们开始配置redux,首先我们在React的src目录中创建一个store文件夹,文件夹中新建一个index.js文件,内容如下所示:
src/store/index.js
import { createStore, combineReducers } from 'redux'
import cadr from './reducers/card'
// 将 Reducer数据合并
const Reducers = combineReducers({
cadr
})
//创建store的对象
const store = createStore(Reducers)
//抛出store的对象值
export {store};
src/store/reducers/card.js -- reducer 数据
const card = (state, actions) => {
let { type, payload } = actions
//判断state是否存在,如果不存在返回默认值
if (!state) {
return {
num : 0
}
}
switch (type) {
case "ADD":
return {
...state,
num: state.num + payload
}
default:
return state
}
}
export default card
简单总结redux的执行流程
View视图中通过dispatch触发action修改state中的数据,state中的数据修改后更新View视图中去,在class组件中,我们通过store中Api方法subscribe() 监听;
state数据的变化,从而更新react组件重新渲染组件。
redux 中间件与持久化
只需要改两个文件即可: 持久化、日志、异步 action
cnpm i redux-persist --save cnpm i redux-logger --save cnpm i redux-thunk --save
src/store/index.js
import { createStore, combineReducers, applyMiddleware } from 'redux'
// reducer 数据
import cadr from './reducers/card'
// 配置数据持久化
import { persistStore, persistReducer} from 'redux-persist'
//导入需要配置的数据源,可以选择,storage,cookie,session等
import storage from 'redux-persist/lib/storage'
// 配置中间件
import thunk from 'redux-thunk'
import logger from 'redux-logger'
// 将 Reducer数据合并
const Reducers = combineReducers({
cadr
})
//在localStorge中生成key为root的值
const persitConfig = {
key: 'roots',
storage,
blacklist:['todolist'] //设置某个reducer数据不持久化,
}
//创建持久化的配置persist的信息
const persist_reducers = persistReducer(persitConfig, Reducers)
// 创建仓库
const store = createStore( persist_reducers, applyMiddleware(thunk,logger) )
//使用persistStore包裹一下
const persistor = persistStore(store);
//抛出store和持久化工具两个对象信息
export { store, persistor }
入口文件 app.jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { HashRouter as Router, Switch, Route, Redirect, withRouter } from "react-router-dom"
// redux 中的数据获取对象信息
import {store, persistor} from './redux/store'
// 导入持久化包包
import { PersistGate } from 'redux-persist/lib/integration/react';
const root = ReactDOM.createRoot(document.getElementById('root'));
const Routes = function () {
return (
<Router>
<Switch>
<Route path="/app" component={App} ></Route>
</Switch>
<Redirect to='/app'></Redirect>
</Router>
)
}
root.render(
// loading 和 persistor是2个必需属性
<PersistGate loading={null} persistor={persistor}>
<Routes></Routes>
</PersistGate>
);
reportWebVitals();
src/App.js 使用步骤
import { store } from './store/index'
import React, { useEffect, useState } from 'react';
import './App.scss';
function App() {
const [state, setstate] = useState(store.getState())
//监听redux数据的变化
store.subscribe(() => {
setstate(store.getState())
})
console.log(state);
return (
<div className="App">
<h3>个人中心--{state.cadr.num}</h3>
<button onClick={()=>store.dispatch({type:"ADD", payload: 2})}>count++</button>
</div>
);
}
export default App;