Задать вопрос
@Boris009

Как реализовать свой простой стейт менеджер для реакта?

На чём базируются стейт менеджеры реакта?
Как реализовать свой, чтобы понять основной принцип работы редакса и мобикса?
  • Вопрос задан
  • 138 просмотров
Подписаться 2 Средний 2 комментария
Пригласить эксперта
Ответы на вопрос 1
В догонку к комментарию:
Сама имплементация
import { useState } from 'react'

class Signal<T> {
    #value: T
    #dispatchers: Set<React.Dispatch<React.SetStateAction<T>>> = new Set()
    constructor(value: T){
        this.#value = value
    }
    get current(): T {
        return this.#value
    }
    set current(value: T){
        if(this.#value !== value){
            this.#value = value
            for(const dispatcher of this.#dispatchers){
                dispatcher(this.#value)
            }
        }
    }
    subscribe(dispatcher: React.Dispatch<React.SetStateAction<T>>): void {
        if(!(this.#dispatchers.has(dispatcher))){
            this.#dispatchers.add(dispatcher)
        }
    }
}

const createSignal = <T>(value: T): Signal<T> => new Signal(value)

const useSignal = <T>(signal: Signal<T>): Signal<T> => {
    const [, dispatcher] = useState(signal.current)
    signal.subscribe(dispatcher)
    return signal
}

export { createSignal, useSignal }

Экспорт сигналов
import { createSignal } from '../lib/signals.ts'

export const counter = createSignal(0)

Компонент, который импортирует и использует сигнал
import { useSignal } from '../lib/signals.ts'
import { counter } from './shared_signals.ts'

export const Button = () => {
    const _counter = useSignal(counter)
    return (
        <button onClick={ () => ++_counter.current }>
            Count is { _counter.current }
        </button>
    )
}

Клиентский скрипт
import { hydrateRoot } from 'react-dom/client'

import { Layout } from './Layout.tsx'
import { Button } from './Button.tsx'

hydrateRoot(
    document,
    <Layout>
        <Button/>
        <Button/>
        <Button/>
        <Button/>
        <Button/>
        <Button/>
        <Button/>
        <Button/>
        <Button/>
        <Button/>
    </Layout>
)

При клике на любую кнопку - используется сигнал, который ты создаёшь один раз, экспортируешь его и можешь использовать где угодно, в любом компоненте. Примерно так эти стейт-менеджеры и работают. Они держат состояние/состояния вне компонентов. А работает это из-за самой природы импортов/экспортов. Если ты экспортируешь, например так: export const obj = { count: 0 }, а затем импортируешь этот obj в другом модуле и увеличиваешь count - то этот count будет увеличен в контексте всех модулей, которые его импортировали, либо будут импортировать.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы