浅析redux
安装
npm install --save redux
原理图
解释:
redux采取一棵==对象树==进行状态的管理,该对象树中仅仅包括一个store来控制各种状态在组件间的流通,使得不同组件之间的状态流通变得容易。但是,store中的内容只能是只读的,修改store中的内容只能通过reducer来进行控制,控制的方法是保留preState,抛出修改过的state副本。
假设现在有3个组件(A,B,C),现在要求A组件控制B组件在C组件上的显示与否,那么整个过程应该是这样的:
- A组件分发一个action(action是store数据中的唯一有效来源)交给store,因此有sotre.dispatch(action);
- 对于C组件B组件需要在上面显示,因此C组件应该订阅状态=>store.subscribe()
redux中的三驾马车
store
store是用在存储redux中action的部件,需要强调的是一个redux应用只能有一个store,如果应用较为复杂则可以将它们组合起来放到store中。
对于store 有以下一些职能:
- 维持应用的 state;
- 提供
getState()方法获取 state; - 提供
dispatch(action)方法更新 state; - 通过
subscribe(listener)注册监听器; - 通过
unsubscribe(listener)返回的函数注销监听器。
import {createStore} from "redux"
const store=createStore(Reducer);//注意,图中store不能处理action,只能交给reducer,因此需要接收reducer参数
export default store;
//组件C根据状态进行改变
useEffect(()=>{
store.subscribe(()=>{
console.log("订阅");
})
return {
console.log("销毁")
}
},[]);
Reducers
reducer是处理action的函数,它接收两个参数即过去的状态
preState、action
const reducer=(preState,action)=>{
...
return preState;
}
export default reducer;
Action
action是用来传递数据的有效载荷,可以理解为告诉reducer你接下来想做什么操作。Action 本质上是 JavaScript 普通对象。action 内==必须==使用一个字符串类型的
type字段来表示将要执行的动作。多数情况下,type会被定义成字符串常量。
/*
* action 类型
*/
export const ADD_TODO = 'ADD_TODO';
export const TOGGLE_TODO = 'TOGGLE_TODO'
export const SET_VISIBILITY_FILTER = 'SET_VISIBILITY_FILTER'
/*
* 其它的常量
*/
export const VisibilityFilters = {
SHOW_ALL: 'SHOW_ALL',
SHOW_COMPLETED: 'SHOW_COMPLETED',
SHOW_ACTIVE: 'SHOW_ACTIVE'
}
/*
* action 创建函数
*/
export function addTodo(text) {
return { type: ADD_TODO, text }
}
export function toggleTodo(index) {
return { type: TOGGLE_TODO, index }
}
export function setVisibilityFilter(filter) {
return { type: SET_VISIBILITY_FILTER, filter }
}
过程总结
案例:组件A控制组件B在组件C上的显示
步骤:
-
对于全局:
-
需要创建store.js:store接收一个reducer用于存储状态,接收组件发送的信息action
-
需要创建reducer,用于对store传递过来的action进行识别并处理state,reducer接收两个参数即preState和action,返回一个state,但是该state不能是在preState基础上进行修改,而应该在preState的副本基础上进行修改(这个可能与内部diff算法有关)
-
//store.js import {createStore} from "redux" const reducer=(preState={isShow:false},action)=>{ switch(action.type){ case:"TURNON" reture {isShow:true}; case:"TURNOFF" return {isShow:false}; default: return preState; //需要注意,此处的reducer并不类似于setState的合并更新,因此对于复杂数据结构需要 //采取immutable或者{...preState,...newState} } } const store = createStore; export default store;
-
-
-
对于组件A:
-
组件A控制B在C上的显示,因此组件A应该dispatch一个action给reducer
-
import React from 'react' import { useState,useEffect } from 'react' import store from "./Store/" export default function A(){ const[State,setState]=useState(); useEffect(()=>{ store.dispatch({ type:"TURNON", ...State })//action必须至少有一个type属性,但是可以携带其它的东西,如这里解构本地State },[State]);//设置只要更新就dispatch一个action return ( <div> ... </div> ) }
-
-
对于组件C:
-
组件C只有获取store中的state这一个功能,redux中state不能修改,就算修改也是在reducer处理后的副本
-
import React from 'react' import store from "./Store/" export default function C(){ const [Show,setShow]=useEffect(true);//组件可以拥有自己的状态,不必把所有的状态存到store中 //如果store中的状态是动态更新的,那么就要订阅它 let STATE; store.subscribe(()=>{ STATE=store.getState();//返回一个对象,其中包括preState以及newState });//只要action被dispatch一次那么内部回调函数就会执行一次 return( <div> ... </div> ) }
-