React(三) 状态管理

102 阅读2分钟

state状态

  • react中,重要的是组件在UI树中的位置,而不是在JSX中的位置
export default function App(){
  if(isFancy){
     return(
       <Counter isFancy={true}
     )
  }else{
  return(
       <Counter isFancy={false}
     )
  }
}

isFancy值变化,不会重置Counter组件及其state,因为修改前后Counter标签都渲染在相同位置,react会认为是同一个组件

  • 如果相同位置渲染不同组件,组件会被移除,连同子树都会重置
  • 如果需要重置state,可以给组件key值

useReducer

复杂组件,可能需要增加/修改/删除操作同一个state,可以把状态修改逻辑统一到一个reducer函数中

function stateReducer(state, action){
   switch(action.type){
     case 'Add':
       ...
     case 'Delete':
       ...
     default: return;
   }
}
---------
const [state, dispatch] = useReducer(stateReducer, initialState);
function handleChange(){
   dispatch({
      type:'Add',
      id:...,
      text:...
   })   
}

状态

围绕状态(不同时刻的数据Model,要展示的内容View),组织展示的逻辑

管理

  • 软件工程的本质 - 管理数据 在数据基础上做处理,数据存哪里,如何展示
  • 淘宝:商家数据的展示,订单数据

设计一个系统,

  1. 有哪些数据
  2. 数据的生命周期
  3. 数据的作用范围
  • 数据库(database):可以一直被看到(聊天内容)
  • localStorage:搜索记录
  • cookie/sessionStorage
  • Project runtime(工程运行时/内存):刷新后会清空
  • component:state,props

状态管理

一般所说的vuex,redux,mobx都属于project runtime范畴,刷新后,js runtime重新执行,数据就会清空

  • 项目运行时,一直全局存在的数据,存在哪里
  • 核心:不被GC - Window/Global,闭包

  1. 组件之外,全局共享数据状态

  2. 修改数据,相关组件可以获取到

    数据改变的时候,执行某个函数

  • 发布订阅 - redux
  • proxy - mobx
  1. 修改状态,触发UI更新

实现一个发布订阅

  1. 2个组件,Child2修改数据,Child1展示数据
const Child1 = () => {
    const [count, setCount] = useState(0);
    useEffect(() => {
        dataObj.subscribe(() => {
            // data改变,这里会执行
            setCount(dataObj.getData())
        })
    })
    return <div>
        <h5>
            Child1中 count为{count}
        </h5>
    </div>
}
const Child2 = () => {
    return <div>
        <button onClick={() => dataObj.changeData(Math.random())}>random</button>
    </div>
}
  1. 闭包实现
export const createData = function (initData) {
    let deps = [];
    let data = initData;
    function subscribe(handler) {
        // 订阅data 的函数 handler,在Data改变的时候执行
        deps.push(handler);
    }
    function changeData(val) {
        data = val;
        deps.forEach(h => h())
    }
    function getData() {
        return data;
    }
    return { subscribe, changeData, getData }
}
export const dataObj = createData(0)

问题

  1. 传递数据的时候,changeData传入的值不固定,可能不规范,unsafe

SAFE By Action

Action,一般由type,payload组成

Reducer

本质是一个计算函数,由action和当前state值,计算出新的state

function reducer(data, action) {
    switch (action.type) {
        case 'ADD':
            return { count: data.count + 1 }
        case 'CHANGE':
            return { count: data.count + action.payload }
        default:
            return data
    }
}
function changeDataByAction(action) {
     data = reducer(data, action);
     deps.forEach(h => h())
}

即redux原理