반응의 VUEX

26459 단어 javascriptvuexreact
본론으로 들어가겠습니다:
React에서는 STATE를 VIEW(STORE 포함)에서 분리해야 합니다.
Redux를 사용할 수 있지만 VUEX를 사용하고 싶습니까? 그런 다음 JON을 사용하십시오!

설치


npm install @priolo/jon

STORE 및 VIEW 생성



import React from "react";
//import ReactDOM from "react-dom";
import { createRoot } from "react-dom/client";
import { createStore, useStore } from '@priolo/jon';

// create STORE-SETUP
const mySetup = {
    // The immutable single source of truth.
    state: {
        value: "init value"
    },
    // Pure functions return a "processed" value of the STATE.
    getters: {
        getUppercase: (state, _, store) => state.value.toUpperCase()
    },
    // They do things! For example: here you have to put API calls to the server
    actions: {
        addAtEnd: (state, payload, store) => {
            store.setValue(state.value + payload)
        }
    },
    // The only ones that can replace the STATE with a new one.
    // NOTE: JON merges the returned property with the previous STATE.
    mutators: {
        setValue: (state, value, store) => ({value})
    }
}

// create STORE
const myStore = createStore(mySetup)

// use STORE in VIEW
function App() {

    // picks up the current STATE of the "myStore" STORE
    const state = useStore(myStore) // "useStore17" if React version is < 18

    // call ACTION. NOTE:  you must pass ONLY the "payload"
    const handleClick = e => myStore.addAtEnd("!")

    // render
    return (<div>
        <h1>{state.value}</h1><h2>{myStore.getUppercase()}</h2>
        <input 
            value={state.value} 
            // call MUTATOR. NOTE: you must pass ONLY the "payload"
            onChange={(e)=>myStore.setValue(e.target.value)} 
        />
        <button onClick={handleClick}>add !</button>
    </div>);
}

// React 18
const root = createRoot(document.getElementById('root'))
root.render(<React.StrictMode><App /></React.StrictMode>)
// React <=17
//ReactDOM.render(<App />, document.getElementById("root") )

codesandbox

자주하는 질문


내 package.json에 다른 라이브러리를 포함하고 싶지 않습니다!



JON을 프로젝트에 복사합니다.

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

// HOOK to use the STORE in React v18
export function useStore(store) {
    return useSyncExternalStore(
        store._subscribe,
        () => store.state
    )
}

// HOOK to use the STORE in React v17
export function useStore17(store) {
    const [state, setState] = useState(store.state)
    useEffect(() => {
        const listener = (s) => setState(s)
        const unsubscribe = store._subscribe(listener)
        return unsubscribe
    }, [store])

    return state
}

export function createStore(setup, name) {

    let store = {

        // the current state of the store
        state: JSON.parse(JSON.stringify(setup.state)),

        // the listeners that are watching the store
        _listeners: new Set(),

        // add listener to the store
        _subscribe: (listener) => {
            store._listeners.add(listener)
            return () => store._listeners.delete(listener)
        },
    }

    // GETTERS
    if (setup.getters) {
        store = Object.keys(setup.getters).reduce((acc, key) => {
            acc[key] = (payload) => setup.getters[key](store.state, payload, store)
            return acc
        }, store)
    }

    // ACTIONS
    if (setup.actions) {
        store = Object.keys(setup.actions).reduce((acc, key) => {
            acc[key] = async (payload) => await setup.actions[key](store.state, payload, store)
            return acc
        }, store)
    }

    // MUTATORS
    if (setup.mutators) {
        store = Object.keys(setup.mutators).reduce((acc, key) => {
            acc[key] = payload => {
                const stub = setup.mutators[key](store.state, payload, store)
                if (stub === undefined) return
                if (Object.keys(stub).every(key => stub[key] === store.state[key])) return
                store.state = { ...store.state, ...stub }
                store._listeners.forEach(listener => listener(store.state))
            }
            return acc
        }, store)
    }

    return store
}


예시:
codesandbox

예, 하지만 어떻게 작동합니까?



실전: STORE에서 MUTATOR가 실행될 때
STORE의 리스너는 사용하는 구성 요소의 후크를 업데이트합니다.
결과적으로 구성요소는 항상 STORE의 "현재"상태를 표시합니다.

닥치고 코드를 보자!



ok ok ... 여기에는 "리스너"가 아닌 "콜백"이 하나만 있습니다.
그러나 그것이 대략 작동하는 방식입니다.
이것은 참조입니다.
https://reactjs.org/docs/hooks-reference.html#usesyncexternalstore

import React, { useSyncExternalStore } from "react";
import { createRoot } from "react-dom/client";

// create EXTERNAL STORE
const myStore = {
    state: {
        value: ""
    },
    callback: null,
    subscribe: (callback) => {
        myStore.callback = callback
        // unsubscribe
        return () => myStore.callback = null
    },
    getSnapshot: () => myStore.state,
    changeState: (newState) => {
        myStore.state = newState
        myStore.callback()
    }
}

// use STORE in VIEW
function App() {

    const currentState = useSyncExternalStore(
        myStore.subscribe,
        myStore.getSnapshot,
    )

    const handleClick = e => myStore.changeState({value: currentState.value + "!"})

    // render
    return (<div>
        <input 
            value={currentState.value} 
            // call MUTATOR. NOTE: you must pass ONLY the "payload"
            onChange={(e)=>myStore.changeState({value:e.target.value})} 
        />
        <button onClick={handleClick}>add !</button>
    </div>);
}

// React 18
const root = createRoot(document.getElementById('root'))
root.render(<React.StrictMode><App /></React.StrictMode>)


codesandbox

나는 그것을 믿지 않는다! 당신이 죽으면? 누가 업데이트합니까?



나는 너를 느낀다!!! 그렇기 때문에 JON을 사용해야 합니다.
그것은 작고 필요한 것만 수행합니다.
내가 죽으면 언제든지 직접 쉽게 편집하거나 기여할 수 있습니다.
...요컨대, 원하는 대로 하세요!

좋은 웹페이지 즐겨찾기