react自定义实现状态管理详解

 更新时间:2024年01月15日 14:37:53   作者:不努力code  
这篇文章主要为大家详细介绍了react如何自定义实现状态管理,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以跟随小编一起学习一下

redux基础实现

myRedux

export const createStore = (reduce) => {
  if (typeof reduce !== 'function') throw new Error('Expected the reducer to be a function.')
  let state,
    listeners = []
  state = reduce()
 
 
  const getState = () => state
  const dispatch = (action) => {
    if(typeof action !== 'object' || typeof action.type !== 'string') throw new Error('Actions must be plain objects.')
    state = reduce(state, action)
    listeners.forEach(listener => listener())
  }
  const subscribe = (listener) => {
    if(typeof listener !== 'function') throw new Error('Expected the listener to be a function.')
    listeners.push(listener)
    return () => listeners = listeners.filter(l => l !== listener)
  }
 
  return {
    getState,
    dispatch,
    subscribe,
  }
}

使用

import React, { useEffect, useState } from 'react'
import { createStore } from './myRedux'
 
 
const reduce = (state = { a: 123 }, action = {}) => {
  state = { ...state }
  switch (action.type) {
    case 'tset':
      state.a = Math.random() * 1000
      return state
    default:
      return state
  }
 
}
const store = createStore(reduce)
 
 
 
export default function Test() {
  const state = store.getState()
  const [_, foceUpdate] = useState(0)
  useEffect(() => {
    store.subscribe(() => {
      foceUpdate(Date.now())
    })
  }, [])
  const change = () => {
    store.dispatch({ type: 'tset' })
  }
  return (
    <div>
      <h1>Test {state.a}</h1>
      <button onClick={change} >change</button>
    </div>
  )
}

react-redux

和源码可能不同,我没看过源码,只是实现一下

react-redux.js

import { useContext, useEffect, useState, createContext } from 'react'
const StoreContext = createContext()
export const Provider = (props) => {
  const store = props.store
  return <StoreContext.Provider value={{ store }}>{props.children}</StoreContext.Provider>
}
 
export const connect = (mapState, mapDispatch) => {
  if (typeof mapState !== 'function') throw new Error('mapState must be an function')
  if (typeof mapDispatch !== 'function') throw new Error('mapDispatch must be an function')
  return (Cpn) => {
    return (props = {}) => {
      const contents = useContext(StoreContext)
      const store = contents.store
      const state = mapState(store.getState())
      const dispatch = mapDispatch(store.dispatch)
      const [_, forceUpdate] = useState(true)
      useEffect(() => {
        store.subscribe(() => {
          forceUpdate(Symbol())
        })
      }, [])
      props = { ...props, ...state, ...dispatch }
      return <Cpn {...props} />
    }
  }
}

使用

import React from 'react'
import { Provider, connect } from './react-redux'
import { createStore } from 'redux'
const reducer = (state = { name: 'test' }, action) => {
  switch (action.type) {
    case 'CHANGE_NAME':
      return { ...state, name: action.name }
    default:
      return state
  }
}
const store = createStore(reducer)
 
function Test2(props) {
  const change = () => {
    props.changeName('test' + Math.random())
  }
  return (
    <div>
      <h1>Test {props.name} </h1>
      <button onClick={change} >change</button>
    </div>
  )
}
const Test3 = connect(
  state => ({ name: state.name }),
  dispatch => ({ changeName: (name) => dispatch({ type: "CHANGE_NAME", name }) })
)(Test2)
 
export default function Test() {
  return (
    <Provider store={store} >
      <Test3 />
    </Provider>
  )
}

模仿pinia方式管理

myPinia.js

export const createStore = (f) => {
  if (typeof f !== 'function') throw new Error('Expected a function')
  const state = f()
  watch(state)
  const proxy = new Proxy(state, {
    get: (target, prop) => {
      const v = target[prop]
      const isState = v instanceof StoreState
      return isState ? v.value : v
    },
    set: () => state,
  })
  const userStore = () => {
    return proxy
  }
 
  return userStore
}
 
const watch = (obj) => {
  Object.keys(obj).forEach((key) => {
    const storeState = obj[key]
    if (storeState instanceof StoreState) {
      let value = storeState.value
      Object.defineProperty(storeState, 'value', {
        get: () => value,
        set: (newValue) => {
          value = newValue
          updateView()
        },
      })
    }
  })
}
 
class StoreState {
  constructor(value) {
    this.value = value
  }
}
 
export const useStoreState = (value) => {
  return new StoreState(value)
}
let listeners = []
const updateView = () => listeners.forEach((f) => f())
export const subscribe = (f) => {
  if (typeof f !== 'function') throw new Error('Expected a function')
  if (!listeners.includes(f)) listeners.push(f)
  return () => (listeners = listeners.filter((l) => l !== f))
}

使用

import React, { useEffect, useState } from 'react'
import { createStore, useStoreState, subscribe } from './myPinia'
 
const userStore = createStore(() => {
  let a = useStoreState(123)
  const change = () => {
    a.value++
  }
  return { a, change }
})
 
export default function Test() {
  const [_, forceUpdate] = useState(0)
  useEffect(() => {
    subscribe(() => forceUpdate(Date.now()))
  }, [])
  const store = userStore()
  const change = () => {
    store.change()
    console.log(store.a);
  }
  return (
    <div>
      <h1>test {store.a}</h1>
      <button onClick={change} >change</button>
    </div>
  )
}

不足的是,还是需要forceUpdate

以上就是react自定义实现状态管理详解的详细内容,更多关于react状态管理的资料请关注脚本之家其它相关文章!

相关文章

  • react diff算法源码解析

    react diff算法源码解析

    这篇文章主要介绍了react diff算法源码解析的相关资料,帮助大家更好的理解和学习使用react,感兴趣的朋友可以了解下
    2021-04-04
  • react实现复选框全选和反选组件效果

    react实现复选框全选和反选组件效果

    这篇文章主要为大家详细介绍了react实现复选框全选和反选组件效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-08-08
  • React实现点击删除列表中对应项

    React实现点击删除列表中对应项

    本文主要介绍了React 点击删除列表中对应项的方法。具有一定的参考价值,下面跟着小编一起来看下吧
    2017-01-01
  • React中如何处理承诺demo

    React中如何处理承诺demo

    这篇文章主要为大家介绍了React中如何处理承诺demo,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • React项目中使用Redux的 react-redux

    React项目中使用Redux的 react-redux

    这篇文章主要介绍了React项目中使用Redux的 react-redux,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-09-09
  • React国际化react-i18next详解

    React国际化react-i18next详解

    react-i18next 是基于 i18next 的一款强大的国际化框架,可以用于 react 和 react-native 应用,是目前非常主流的国际化解决方案。这篇文章主要介绍了React国际化react-i18next的相关知识,需要的朋友可以参考下
    2021-10-10
  • 详解React hooks组件通信方法

    详解React hooks组件通信方法

    这篇文章主要介绍了React hooks组件通信,在开发中组件通信是React中的一个重要的知识点,本文通过实例代码给大家讲解react hooks中常用的父子、跨组件通信的方法,需要的朋友可以参考下
    2022-07-07
  • React可定制黑暗模式切换开关组件

    React可定制黑暗模式切换开关组件

    这篇文章主要为大家介绍了React可定制黑暗模式切换开关组件示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10
  • React不使用requestIdleCallback实现调度原理解析

    React不使用requestIdleCallback实现调度原理解析

    这篇文章主要为大家介绍了React不使用requestIdleCallback实现调度原理解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • 详解如何使用React Redux实现异步请求

    详解如何使用React Redux实现异步请求

    这篇文章主要为大家详细介绍了如何使用React Redux实现异步请求,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考一下
    2025-01-01

最新评论