React18을 사용해야 하는 좋은 이유: useSyncExternalStore

간단한 ToDo를 생각해 봅시다.
이것은 당신의 동료가 휴가를 가기 전에 💩 당신에게 선물로 남긴 것입니다:

codesandbox
index.js에는 다른 함수를 호출하는 구성 요소 간에 전달되는 구성 요소 내 함수가 엉망입니다.
그리고 그것이 실제 프로젝트라면 훨씬 더 나쁠 것입니다.
COMPONENT TREE가 더 깊기 때문에
COMPONENT의 중첩은 복잡성을 배가시킵니다!

스토어를 만들자



STORE에 넣기 위해 COMPONENT에서 LOGIC 및 STATUS를 추정해 보겠습니다.

const myStore = {

    callbacks: new Set(),
    subscribe: (callback) => {
        myStore.callbacks.add(callback)
        return () => myStore.callbacks.delete(callback)
    },
    getSnapshot: () => myStore.state,
    changeState: (newState) => {
        myStore.state = newState
        myStore.callbacks.forEach( cb => cb() )
    },

}


codesandbox

useSyncExternalStore을 사용하는 STORE의 일반적인 구현입니다.
새로운 React18 후크(하지만 React17에서도 가능합니다!).
그러므로:
  • subscribeSTORE의 STATE가 변경될 때 호출할 콜백을 저장합니다.
  • getSnapshot현재 STATE를 반환합니다.
  • changeState하나의 STATE를 다른 STATE로 교환하는 것이 편리합니다.
    STATE는 불변임을 기억하세요!
    그리고 모든 등록callbacks에게 변경
  • 을 알립니다.

    주를 입력하십시오




    const myStore = {
        ...
        state: {
            todos: [
                { desc : "init value" },
            ],
            todoInEdit: {
                desc: ""
            },
        },
        ...
    }
    


    codesandbox

    이것은 우리의 VIEW(이 경우에는 ToDo 앱)가 어떻게 생겼는지에 대한 그림입니다.
    STATE는 VIEW의 단 하나의 뷰를 나타냅니다.

    돌연변이를 입력




    const myStore = {
        ...
        setTodos: todos => myStore.changeState({
            ...myStore.state,
            todos
        }),
        setTodoInEditProp: prop => myStore.changeState({
            ...myStore.state,
            todoInEdit: { ...myStore.state.todoInEdit, ...prop }
        }),
        ...
    }
    


    codesandbox

    수정된 STATE를 전달하여 changeState를 실행합니다.
    결과적으로 구성 요소에 대한 변경 사항을 알립니다.
    (전에 말했듯이)

    액션을 추가하자




    const myStore = {
        ...
        deleteTodo: (index) => {
            const newTodos = myStore.state.todos.filter ((_,i)=>i!==index)
            myStore.setTodos(newTodos)
        },
        addTodoInEdit: () => {
            const newTodos = [...myStore.state.todos, myStore.state.todoInEdit]
            myStore.setTodos(newTodos)
            myStore.setTodoInEditProp({desc: ""}) 
        },
        ...
    }
    


    codesandbox

    VIEW를 업데이트하자




    function App() {
        return (<div>
            <List />
            <Form />
        </div>);
    }
    
    function List() {
        const state = useSyncExternalStore(store.subscribe, store.getSnapshot)
    
        return (
            <ul>
                {state.todos.map((td, index) => (<li>
                    {td.desc}
                    <button onClick={_=>store.deleteTodo(index)}>
                        Delete
                    </button>
                </li>))}
            </ul>
        )
    }
    
    function Form() {
        const state = useSyncExternalStore(store.subscribe, store.getSnapshot)
        const handleChange = e => store.setTodoInEditProp({desc:e.target.value})
        const handleClickAdd = _ => store.addTodoInEdit()
    
        return (<div>
            <input
                value={state.todoInEdit.desc}
                onChange={handleChange}
            />
            <button onClick={handleClickAdd}>Add</button>
        </div>)
    }
    


    codesandbox

    STORE는 LOGIC 및 STATE 관리를 담당합니다.
    VIEW는 단순히 STORE와 동기화됩니다.

    구성 요소가 더 읽기 쉽습니다.

    문제없이 이동할 수 있습니다.
    예를 들어 List는 아무 것도 변경하지 않고 다른 구성 요소 안에 넣을 수 있습니다.
    더 이상 PARENT에 "의존"하지 않기 때문입니다.
    사실List에는 속성이 없습니다.

    이것은 또한 단위 테스트를 더 쉽게 만듭니다.

    요컨대, 행동을 변경해야 하는 경우 상점을 살펴봐야 합니다.
    디스플레이를 변경해야 하는 경우 구성 요소에 따라 조치를 취해야 합니다.



    React에는 (일반적으로) STATE 관리를 허용하는 많은 라이브러리가 있습니다.
    당연히 하나 만들었어요 😃
    제 생각에는 다른 것들에 비해
    1) 후드 아래에서 어떻게 작동하는지 완벽하게 확인합니다. 마술 없음
    2) 초경량
    3) 이것만 하고 다른 것은 하지 않는다.

    원하시면 확인해보세요 here

    좋은 웹페이지 즐겨찾기