其他分享
首页 > 其他分享> > React-Redux、Recoil、useContext 做个简单的对比

React-Redux、Recoil、useContext 做个简单的对比

作者:互联网

关注公众号: 微信搜索 前端工具人 ; 收货更多的干货

文章来源: 自己掘金文章 https://juejin.cn/post/7073035305430810637/

React 生态丰富衍生了许多 状态管理 轮子;

开发时如何选择状态管理,也有些犯难;

在这把我所理解的、项目中用到过的(React-Redux, Recoil, useContext)做个简单的对比,仅供参考;

一、个人建议

React-Redux

Recoil

useContext

自己日常开发

当然还有许多优秀的状态管理插件, MobXhox 等等,自己没怎么用就不多做讨论了。

以下介绍有不对的,或者有更好的方法,请留言,先谢谢大佬

因为并不是一直在用 react , 日常开发用的比较杂(vue3,react、flutter、electron都用)、所以见解不是很深,只是把日常开发贴出来,仅供参考

二、React-Redux

个人觉得目前来说 React-Redux 相对于其他轮子,优势没那么明显了;

由于自己是从 Redux 过来的,前期轮子并不是很多选择,所以旧项目一直使用着 React-Redux, 重构时也没替换;

缺点

优点

React-Redux 架构组件思想我觉得非常的好, 很适用开发时对组件的一个拆分的粒度;

React-Redux 将所有组件分成两大类

  1. 只负责 UI 的呈现,不带有任何业务逻辑
  2. 没有状态(即不使用state这个变量)
  3. 所有数据都由参数(props)提供
  4. 不使用任何 ReduxAPI
  5. 又称纯组件,即纯函数一样,纯粹由参数决定它的值, 没有任何副作用
  1. 负责管理数据和业务逻辑,不负责 UI 的呈现
  2. 带有内部状态, 可使用 ReduxAPI
  3. 包含输入逻辑:外部的数据(即state对象)如何转换为 UI 组件的参数
  4. 输出逻辑:用户发出的动作如何变为 Action 对象,从 UI 组件传出去

UI 组件负责 UI 的呈现,容器组件负责管理数据和逻辑

React-Redux 规定所有的 UI 组件都由用户提供,容器组件则由 React-Redux自动生成。也就是说,用户负责视觉层,状态管理则是全部交给它

如果一个组件既有 UI又有业务逻辑,那么将它拆分成:外面是一个容器组件,里面包了一个UI 组件。前者负责与外部的通信,将数据传给后者,由后者渲染出视图

代码片段

// store/index.js
// 以下类型涉及其他地方引入,就改为 any 了
import { createStore } from 'redux';

export const Types = {
  CHANGE_DEVELOP: 'CHANGE_DEVELOP',
  CHANGE_LANGUAGE: 'CHANGE_LANGUAGE'
}
const onChangeDevelop = <T = string>(val: T) => {
  return {
    type: Types.CHANGE_DEVELOP,
    payload: val
  }
}
const onChangeLanguage =  <T = string>(val: T) => {
  return {
    type: Types.CHANGE_LANGUAGE,
    payload: val
  }
}
const baseState = {
    language: 'zh',
    developer: '前端工具人'
}
interface IAction {
  type: string,
  payload: any
}
const reducer = (state = baseState, action: IAction) => {
    switch (action.type) {
        case Types.CHANGE_LANGUAGE:
          return { ...state, language: action.payload};
        case Types.CHANGE_DEVELOP:
          return { ...state, developer: action.payload };
        default:
          return state;
    }
}
const configureStore = () => createStore(reducer)
export default configureStore;

// 项目入口 App.tsx
import { Provider } from 'react-redux'
import configureStore from './store/index'
const store = configureStore()
ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
     <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
);

// 使用 Home.tsx
import {useDispatch, useSelector} from 'react-redux'
const Header = () => {
    const dispatch = useDispatch()
    const developer = useSelector((state) => state.developer)
    const onChangeDeveloper = ()=> { dispatch({ type:  Types.CHANGE_DEVELOP, developer: '修改后的developer' }) }
}

三、Recoil

优势

我引用的是 Recoil 文档 的介绍, 吧啦吧啦一堆 详情直戳

代码片段

// store/index.js
// 以下类型涉及其他地方引入,就改为 any 了
import React from 'react';
import { atom, selector, } from 'recoil';

// Recoil key 集合
const KEYS = {
    COMMON_STATE: 'commonState'
    PRODUCT_COUNT: 'productCount'
}
interface IBaseStore {
  language: string,
  developer: string,
  email: string,
  children: React.ReactNode[] | React.ReactNode
}
export const commonState = atom<IBaseStore>({
  key: KEYS.COMMON_STATE,
  default: {
    language: 'zh',
    developer: 'laisheng',
    children: [],
    email: '18826262167@163.com'
  }
})
export const productCount = selector({
  key:  KEYS.PRODUCT_COUNT,
  get: ({get}) => {
    return get(commonState)
  },
  set:({set, reset, get}, newValue) => {
   console.log(newValue)
 }
})

// App.tsx
import { RecoilRoot } from 'recoil';
const App: React.FC<AppProps> = () => {
  return (
    <RecoilRoot>
      <Router>
        <RouterPage />
      </Router>
    </RecoilRoot>
  )
}
export default App

// 使用 Home.tsx
import {useRecoilState, useRecoilValue} from 'recoil'
import { commonState } from '@/store'
const Header = () => {
    const [comState, setComState] = useRecoilState(commonState);
    setComState({ ...comState, developer: '更新工具人' })
}

四、useContext

这个作为 React-Hooks 自带的 buff 还是非常的ok

这个就没啥好介绍的了, 直接上代码片段吧

// Home.tsx
// 以下类型涉及其他地方引入,就改为 any 了
import React, { createContext, useMemo, useContext, useEffect, useReducer, useRef, useState, memo, useCallback } from 'react';

interface IHomeContext<T> {
  state: T,
  dispatch: any
}
interface IState {
  communityId: string | number,
  communityName: string,
  macAddress: string | number,
  doorControlName: string,
}
const homeState = {
  communityId: '',
  communityName: '',
  macAddress: '',
  doorControlName: ''
}
const HomeContext = createContext<IHomeContext<IState>>({
  state: homeState,
  dispatch: () => [],
})

// 类型这块这里就直接贴any了,因为要从其他地方导入类型
const onChangeHomeState = (state: any, data: any): IState => {
  for (let key in data) {
    // 避免 useContext 存储未定义的字段
    if (key in state) state[key] = data[key]
  }
  return { ...state }
}

const Home: React.FC = () => {
  const [state, dispatch] = useReducer(onChangeHomeState, homeState)
  return (
    <HomeContext.Provider value={{ state: useMemo(() => state, [state]), dispatch }}>
      <div className="home-container">
        <main>
          <Header />
          ...
        </main>
      </div>
    </HomeContext.Provider>
  )
}

// 使用 
const Header = () => {
    const { state, dispatch }  = useContext(HomeContext)
    // age、 address onChangeHomeState 并不会处理, 更新的只有 communityId
    dispatch({ 'communityId': 13, age: 18, address: '深圳' })
}

标签:状态,const,React,state,Recoil,组件,useContext,Redux
来源: https://www.cnblogs.com/ljx20180807/p/15986358.html