react-object-model: 面向对象的 react 状态管理,只依赖 react hooks,简单、易用、高效

2021-04-17 13:04:20 +08:00
 SHF

react-object-model

面向对象的 react 状态管理,只依赖 react hooks,简单、易用、高效

Github

https://github.com/ShenHongFei/react-object-model

Usage

import React from 'react'
import ReactDOM from 'react-dom'

import Model from 'react-object-model'

function Example () {
    const { value } = counter.use(['value'])
    
    return <div>
        <div>counter.value = {value}</div>
        <div>
            <button onClick={ () => { counter.increase() } }>+1</button>
            
            <button onClick={ async () => {
                await counter.increase_async()
                console.log('counter.value', counter.value)
            } }>+1 (delay 2s)</button>
            
            <button onClick={ () => { counter.reset() } }>reset</button>
        </div>
    </div>
}


class Counter extends Model <Counter> {
    value = 0
    
    reset () {
        this.set({ value: 0 })
    }
    
    increase () {
        this.set({ value: this.value + 1 })
    }
    
    async increase_async () {
        await new Promise(resolve => { setTimeout(resolve, 2000) })
        this.set({ value: this.value + 1 })
    }
}

let counter = new Counter()

ReactDOM.render(<Example/>, document.querySelector('.root'))

Implementation

import { useEffect, useRef, useState } from 'react'

export class Model <T> {
    protected _selectors: Map<React.MutableRefObject<(keyof T)[]>, ({ }) => void>
    
    protected _state: any
    
    constructor () {
        Object.defineProperty(this, '_selectors', {
            configurable: true,
            enumerable: false,
            writable: true,
            value: new Map<React.MutableRefObject<(keyof T)[]>, ({ }) => void>()
        })
        
        Object.defineProperty(this, '_state', {
            configurable: true,
            enumerable: false,
            writable: true,
            value: { }
        })
    }
    
    use (selector?: (keyof T)[]) {
        const ref = useRef(selector)
        this._selectors.set(ref, useState({ })[1])
        useEffect(() => {
            return () => { this._selectors.delete(ref) }
        }, [])
        return this as any as T
    }
    
    set (data: Partial<T>) {
        Object.assign(this, data)
        this.render()
    }
    
    render () {
        this._selectors.forEach( (setState, { current: selector }) => {
            if (selector && !selector.find( (key: keyof T) => this[key as any] !== this._state[key] ))
                return
            setState({ })
        })
        this._state = { ...this }
    }
}

export default Model
1248 次点击
所在节点    分享创造
2 条回复
netnr
2021-04-21 18:58:37 +08:00
怎么回事,撞头像了
SHF
2021-04-21 21:13:15 +08:00
@netnr 巧了~

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/771266

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX