반응의 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을 사용해야 합니다.
그것은 작고 필요한 것만 수행합니다.
내가 죽으면 언제든지 직접 쉽게 편집하거나 기여할 수 있습니다.
...요컨대, 원하는 대로 하세요!
Reference
이 문제에 관하여(반응의 VUEX), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/air_choosy/vuex-in-react-48hc텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)