useReducer 및 Context를 사용하여 상태 관리 시작
useReducer
갈고리와 React 상하문 본고에서 우리는
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
훅을 사용하는 모든 구성 요소가 다시 렌더링됩니다.우리의 예시에서 useContext
과 Name
부품에는 모두 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 예시 프로그램을 몰래 보셔도 됩니다!만약 당신에게 문제가 있거나 내가 조사해야 할 주 관리 도서관에 대한 건의가 있다면 저에게 알려 주십시오.
읽어주셔서 감사합니다!
Reference
이 문제에 관하여(useReducer 및 Context를 사용하여 상태 관리 시작), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/emma/getting-started-with-state-management-using-usereducer-and-context-4a6k텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)