useReducer 및 Context를 사용하여 상태 관리 시작

React 응용 프로그램의 상태 관리 라이브러리를 선택하는 것은 까다로울 수 있습니다.선택 사항은 다음과 같습니다.
  • React의 useReducer 갈고리와 React 상하문
  • 사용
  • 은 장기적으로 유행하는 도서관이다. 예를 들어 Redux 또는 MobX
  • 새로운 것을 시도해 보세요. 예를 들어 react-sweet-state 또는 Recoil (모험을 좋아한다면!)
  • 이 시리즈는 보다 현명한 의사 결정을 돕기 위해 다양한 상태 관리 솔루션을 사용하여 업무 목록 응용 프로그램을 만드는 방법을 신속하게 설명하고자 합니다.
    본고에서 우리는 useReducer 갈고리와 React 상하문을 결합하여 우리의 예시 응용 프로그램을 구축하고 React Tracked이라는 라이브러리를 신속하게 돌아갈 것이다.
    계속하려면 이 가이드에서 만든 예제 애플리케이션에 대해 react-state-comparison의 저장소를 만들었습니다.

    This post assumes knowledge of how to render functional components in React, as well as a general understanding of how hooks work.



    애플리케이션 기능 및 패브릭
    이 애플리케이션에서 구현할 기능은 다음과 같습니다.
  • 편집 대기 사항 목록 이름
  • 작업 작성, 삭제 및 편집
  • 응용 프로그램의 구조는 다음과 같습니다.
    src
      common
        components # component code we can re-use in future posts
      react # the example app we are creating in today's post
        state # where we initialise and manage our state
        components # state-aware components that make use of our common components
    

    일반 구성 요소 만들기
    우선, common 폴더에 구성 요소를 만들 것입니다.이 '보기' 구성 요소들은 우리가 어떤 상태 관리 라이브러리를 사용하고 있는지 모른다.그것들의 유일한 목적은 하나의 구성 요소를 보여주고 우리가 도구로 전달한 리셋을 사용하는 것이다.이 시리즈의 후속 글에서 다시 사용할 수 있도록 공공 폴더에 저장합니다.
    다음과 같은 네 가지 구성 요소가 필요합니다.
  • NameView - 대기사항 목록 이름
  • 을 편집하는 필드
  • CreateTaskView - "만들기"단추가 있는 필드이므로 새 작업
  • 을 만들 수 있습니다.
  • TaskView - 작업의 확인란, 작업 이름 및 삭제 버튼
  • TasksView - 모든 작업 반복 및 표시
  • 예를 들어, Name 구성 요소의 코드는 다음과 같습니다.
    // src/common/components/name
    
    import React from 'react';
    
    const NameView = ({ name, onSetName }) => (
        <input
            type="text"
            defaultValue={name}
            onChange={(event) => onSetName(event.target.value)}
        />
    );
    
    export default NameView;
    
    이름을 편집할 때마다 우리는 입력한 현재 값 (onSetName 대상을 통해 접근) 을 사용하여 event 리셋을 호출합니다.

    In a real-life app, you might think about holding off on making this call until the user has saved the task’s name. You could either have a "save" button for this, or listen for the user to leaving the input field by clicking away or pressing enter.


    다른 세 구성 요소의 코드는 비슷한 패턴을 따라 common/components 폴더에서 볼 수 있습니다.

    우리 상점의 모양을 정의하다
    다음에 우리는 우리의 상점이 어떤 모양인지 고려해야 한다.local state의 상태는 각 구성 요소에 있습니다.반대로 상점은 중심 위치입니다. 응용 프로그램에 모든 상태를 설정할 수 있습니다.
    대기사항 목록의 이름과 ID에 따라 매핑되는 모든 작업을 포함하는 작업 매핑을 저장합니다.
    const store = {
      listName: 'To-do list name',
      tasks: {
        '1': {
          name: 'Task name',
          checked: false,
          id: 1,
        }
      }
    }
    

    우리의 생활과 행동을 창조하다
    우리는 감축기와 조작을 사용하여 저장된 데이터를 수정한다.
    액션의 작업은 상점에 대한 수정을 요청하는 것이다.다음과 같이 말합니다.

    “Hey, I want to change the to-do list’s name to be 'Fancy new name'”.


    감속기의 업무는 상점을 수정하는 것이다.감속기가 요청을 받고 다음을 수행합니다.

    "Okay, I will change the to-do list's name to be 'Fancy new name'"



    행동
    각 작업에는 두 개의 값이 있습니다.
  • 작업의 type - 목록의 이름을 업데이트하려면 유형을 updateListName으로 정의할 수 있습니다
  • 동작의 payload - 목록의 이름을 업데이트하려면 유효 부하에'신기한 새 이름'
  • 이 포함됩니다updateListName 보내기 작업은 다음과 같습니다.
    dispatch({ 
        type: 'updateListName', 
        payload: { name: 'Fancy new name' } 
    });
    

    감속기
    감속기는 우리가 동작을 어떻게 사용하는지 정의하는 유효한 하중 수정 상태이다.이 함수는 저장된 현재 상태를 첫 번째 매개변수로 지정하고 작업을 두 번째 매개변수로 지정하는 함수입니다.
    // src/react/state/reducers
    
    export const reducer = (state, action) => {
        const { listName, tasks } = state;
        switch (action.type) {
            case 'updateListName': {
                const { name } = action.payload;
                return { listName: name, tasks };
            }
            default: {
                return state;
            }
        }
    };
    
    
    switch 문장을 사용하면, Reducer는 작업에 일치하는 사례를 찾으려고 시도합니다.만약 작업이 Reducer에 정의되지 않았다면, 우리는 default 대소문자를 입력하고 state 대상을 되돌려줄 것입니다.
    정의된 경우 state 객체의 수정 버전을 계속해서 반환합니다.이 예에서는 listName의 값을 변경합니다.
    여기서 주의해야 할 가장 중요한 것은 우리가 받은 상태 대상을 직접 수정한 적이 없다는 것이다.e, g. 이렇게 하지 마십시오.
    state.listName = 'New list name';
    
    상점의 값이 변경되었을 때 프로그램이 다시 렌더링되어야 하지만,state 대상을 직접 수정하면 이런 상황이 발생하지 않습니다.우리는 새로운 대상으로 돌아가는 것을 확보해야 한다.이 작업을 수동으로 수행하지 않으려면 immer 라이브러리에서 안전하게 수행할 수 있습니다.

    우리 가게를 창설하고 초기화하다
    Reducer와 actions가 정의되었으므로 React Context와 useReducer을 사용하여 스토리지를 생성해야 합니다.
    // src/react/state/store
    
    import React, { createContext, useReducer } from 'react';
    import { reducer } from '../reducers';
    import { initialState } from '../../../common/mocks';
    
    export const TasksContext = createContext();
    
    export const TasksProvider = ({ children }) => {
        const [state, dispatch] = useReducer(reducer, initialState);
        return (
            <TasksContext.Provider value={{ state, dispatch }}>
                {children}
            </TasksContext.Provider>
        );
    };
    
    
    useReducer 갈고리는 앞에서 정의한 Reducer 함수를 사용하여 Reducer를 만들 수 있도록 합니다.초기 상태 객체가 다음과 같이 보일 수도 있습니다.
    const initialState = {
      listName: 'My new list',
      tasks: {},
    };
    
    응용 프로그램 주위에서 공급자를 포장할 때, 모든 구성 요소는 state 대상에 접근하여 필요한 내용을 보여주고, dispatch 함수를 사용하여 사용자와 UI가 상호작용할 때 조작을 조정할 수 있습니다.

    공급업체를 사용하여 어플리케이션 포장src/react/components 폴더에 React 애플리케이션을 만들어 새로운 공급업체로 포장해야 합니다.
    // src/react/components
    import React from 'react';
    
    import { TasksProvider } from '../state/store';
    
    import Name from './name';
    import Tasks from './tasks';
    import CreateTask from './create-task';
    
    const ReactApp = () => (
        <>
            <h2>React with useReducer + Context</h2>
            <TasksProvider>
                <Name />
                <Tasks />
                <CreateTask />
            </TasksProvider>
        </>
    );
    
    export default ReactApp;
    
    
    모든 상태 감지 구성 요소 here을 사용할 수 있습니다. Name을 살펴보겠습니다.

    액세스 데이터 및 스케줄링 작업
    이전에 생성된 NameView 구성 요소를 사용하면 Name 구성 요소를 다시 만들 것입니다.useContext 훅을 사용하여 컨텍스트에서 값을 액세스할 수 있습니다.
    import React, { useContext } from 'react';
    import NameView from '../../../common/components/name';
    import { TasksContext } from '../../state/store';
    
    const Name = () => {
        const {
            dispatch,
            state: { listName }
        } = useContext(TasksContext);
    
        const onSetName = (name) =>
            dispatch({ type: 'updateListName', payload: { name } });
    
        return <NameView name={name} onSetName={onSetName} />;
    };
    
    export default Name;
    
    우리는 state 값을 사용하여 목록의 이름을 나타낼 수 있으며, dispatch 함수를 사용하여 이름을 편집할 때 작업을 보낼 수 있다.그리고 우리의 감속 기회는 상점을 갱신할 것이다.이렇게 간단해!

    어경에 반응하는 문제
    불행히도 이런 단순성은 함정을 가져왔다.React Context를 사용하면 useContext 훅을 사용하는 모든 구성 요소가 다시 렌더링됩니다.우리의 예시에서 useContextName 부품에는 모두 Tasks 갈고리가 있다.목록의 이름을 수정하면 Tasks 어셈블리가 다시 렌더링되고 그 반대의 경우도 마찬가지입니다.
    이것은 우리의 소형 업무 목록 프로그램에 어떠한 성능 문제도 일으키지 않지만, 응용 프로그램이 커지면서 대량으로 다시 렌더링하는 것은 성능에 좋지 않다.React Context와use Reducer의 사용 편의성에 재렌더링 문제가 없기를 원한다면, 변통 라이브러리를 사용할 수 있습니다.

    React-Tracked로 React-context 교체
    React Tracked은 초소형(1.6kB) 라이브러리로React 상하문에서 포장기를 충당한다.
    Reducer와 actions 파일은 변경되지 않지만 store 파일을 다음 파일로 대체해야 합니다.
    //src/react-tracked/state/store
    
    import React, { useReducer } from 'react';
    import { createContainer } from 'react-tracked';
    import { reducer } from '../reducers';
    
    const useValue = ({ reducer, initialState }) =>
        useReducer(reducer, initialState);
    
    const { Provider, useTracked, useTrackedState, useUpdate } = createContainer(
        useValue
    );
    
    export const TasksProvider = ({ children, initialState }) => (
        <Provider reducer={reducer} initialState={initialState}>
            {children}
        </Provider>
    );
    
    export { useTracked, useTrackedState, useUpdate };
    
    
    액세스 상태 및 할당 값에는 세 개의 훅이 있습니다.
    const [state, dispatch] = useTracked();
    const dispatch = useUpdate();
    const state = useTrackedState();
    
    이게 유일한 차이야!현재 목록의 이름을 편집하면 작업이 다시 나타나지 않습니다.

    결론useReducer을 React Context와 함께 사용하면 관리 상태를 빠르게 시작할 수 있습니다.그러나 상하문을 사용할 때 다시 보여주는 것이 문제가 될 수 있다.만약 당신이 빠른 해결 방안을 찾고 있다면, React Tracked는 깔끔한 작은 라이브러리입니다. 당신은 그것을 대체할 수 있습니다.
    오늘 소개한 코드를 보려면 react-state-comparison으로 가서 전체 예시를 보십시오.다음 주에 저희가 사용할 레드ux 예시 프로그램을 몰래 보셔도 됩니다!만약 당신에게 문제가 있거나 내가 조사해야 할 주 관리 도서관에 대한 건의가 있다면 저에게 알려 주십시오.
    읽어주셔서 감사합니다!

    좋은 웹페이지 즐겨찾기