Задать вопрос
Контакты
Местоположение
Россия, Свердловская обл., Каменск-Уральский

Наибольший вклад в теги

Все теги (2)

Лучшие ответы пользователя

Все ответы (7)
  • Как реализовать свой простой стейт менеджер для реакта?

    В догонку к комментарию:
    Сама имплементация
    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 будет увеличен в контексте всех модулей, которые его импортировали, либо будут импортировать.
    Ответ написан
    Комментировать