react js自定义实现状态管理

发布时间:2024年01月15日

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>
  )
}

?

模仿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

?

文章来源:https://blog.csdn.net/qq_41144591/article/details/135543908
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。