自己写项目是尽量不用这些状态库, 一大堆的模板代码,配置环境都得半天,特别是redux, 虽然目前提供一系列脚手架redux-toolkit进行优化,但还是特别麻烦, 还有一个原因:就是项目开发初级阶段, 需求不断在迭代,状态设计不可能一次就好,总是需要来回重构.
跨组件状态传递的常用方法
状态库的引用主要是为了解决跨组件之间状态的传递,和数据的跟踪. 先梳理一些跨组件传递的方法
- 兄弟组件, 把状态抽取到父组件
- event emit / dom event
- localstore
- 参数通过url参数传递
- 注意 参数编码
参考 stackoverflowconst serialize = (obj) => Object.entries(obj) .map((i) => [i[0], encodeURIComponent(i[1])].join("=")) .join("&"); - encodeURIComponent() vs encodeURI
后者会编译更多字符,如#号,一般都用 encodeURIComponent ,除A-Z a-z 0-9 - _ . ! ~ * ' ( )以外的所有字符都会被编译
- 注意 参数编码
- react中useState+useContext+useReducer 官网有完整示例
回顾一下项目开始阶段
-
我开始就是通过合理地设计组件和(1)状态向上抽取 来进行兄弟组件的状态传递.
-
跨页面组件的状态我是通过url(4)进行传递
-
一些不常变动的需要多个组件共用的状态我用loaclstore共享, 需要监听storage的变化, 特别是ahooks最新版本有提供一个现成的方法useLocalStorageState,当然以下方法都能达到状态传递的效果,值也是响应式的
- useLocalStorageState
- useSessionStorageState
- useCookieState
-
也可以用event emit, ahooks也提供了一个方法
- useEventListener
import React, { useState, useRef } from 'react'; import { useEventListener } from 'ahooks'; export default () => { const [value, setValue] = useState(0); const ref = useRef(null); useEventListener( 'click', () => { setValue(value + 1); }, { target: ref }, ); return ( <button ref={ref} type="button"> You click {value} times </button> ); };也可以自定义事件 CustomEvent
useEventListener('set-token', () => { SetToken() }) const tokenEvent = new CustomEvent('set-token', { detail: {}, // 如果有参数可以放在这咯 bubbles: false, cancelable: false, composed: false, }) tokenEvent(tokenEvent) -
为了约束状态的统一入口,最后用(5)useState+useContext+useReducer重构. 但此时已经没必要了, 状态结构基本已经稳定, 可以找第三方框架来接管这些状态
第三方主流框架
redux
排除,感觉没必要
redux-toolkit能方便一点点, 大家可以自己去官网文档
redux-toolkit.js.org/api/getDefa…
github.com/reduxjs/red…
redux-toolkit.js.org/usage/usage…
react-redux.js.org/tutorials/t…
mobx
hooks存在闭包问题,大量hooks必然增大应用内存 其实 Hooks 这些问题都是因为没有一个公共的空间来共享数据导致的,在 Class 组件中,我们有 this , 在 Vue3 中,我们有 setup作用域 。Hooks 你只能依靠useRef + ref.current 来 hack 了。但它极其不优雅,
这时候你是不是也想到了我们的 Mobx ,它不就是提供统一作用域的神器吗, 之前只有class写法, 后来也推出了hooks的写法
在数据结构比较复杂的话,性能优于redux. 但项目中其实没那么多讲究, mobx和redux同样经典, 自己喜欢哪个就用哪个, 但redux太麻烦, 所以自己不喜欢用. 而且mobx对异步的处理比较友好,不需要引入其他中间件
mobx可以直接更新状态,但react要通过action和reducer更新状态
mobx只重新渲染受影响的组件 ,但react需要自己通过优化来实现高效渲染
react需要自己写大量的memo, useMemo,useCallBack去优化这个性能
mobx-react-lite requires React 16.8 or higher.
mobx.js.org/README.html
mobx.js.org/react-integ…
www.npmjs.com/package/mob…
moxb中的一些使用和概念
- observer
Mobx 使组件响应数据状态的变化主要有以下三种方式:
- observer HOC
- Observer Component
<Observer>{renderFn}</Observer> - useObserver hooks
传统React.Component 中使用 mobx 时候 我们使用 observer HOC 的方式 ,它的主要能力是给类组件提供 pure component 的能力,可以将类组件的 props 和 state 转换为 observable 态,从而来响应数据状态的变化。 同样,这种 HOC 形式也可以直接在 Hooks 中正常使用。 但是 Hooks 并不推荐 HOC 的方式。于是乎就出现了 useObserver。
以上三种具体区别和场景使用如下
www.jianshu.com/p/c21907121… @NANAISNANA
- useLocalObservabl
使用给定的属性、方法和计算值创建可观察对象。
useLocalObservable是以下各项的简写:
const [state] = useState(() => observable(initializer(), annotations, { autoBind: true }))
zustand
简单,功能也很强大,和ts集成也很方便, 也提供了相关hooks使用,推荐, 也不用像redux引入同步,异步的概念