TODO 응용 프로그램을 통해use Reducter+useContext에 들어가기
116327 단어 ReactTypeScript자습서tech
개시하다
《React Hooks 및 Type Script를 사용한 간단한 TODO 적용》의 속편.
저번까지의 토도.
useReducter 가져오기
useReducer
는 useState
대체품으로 여러 값을 뛰어넘는 복잡한state 논리가 존재하거나 이전state를 바탕으로 다음state를 확정해야 하는 상황에서 유용하다.1. useReducter의 구문
const [state, dispatch] = useReducer(reducer, 'ステートの初期値');
reducer
상태 업데이트에 사용되는 함수dispatch
는 실행reducer
에 사용되는 호출 함수2. 디스패치를 통해 Reducter 방법을 호출
이전에 실행된 곳
setState(newState)
의 업데이트는 다음과 같은 상태입니다.dispatch(action);
action
는 표지부type
의 속성과 값 속성으로 구성된 대상의 동작을 지시한다.구체적으로 아래와 같다.// count ステートを +1 する
dispatch({ type: 'add', value: state.count + 1 });
/*
* 以下と(ほぼ)同義
* setCount((count) => count + 1);
*/
3. 자르기 유형 정의 파일
TODO 응용 프로그램에 사용되는 두 가지 유형의 앨리어스와 상태 유형을 유형 정의 파일로 나열합니다.
src/@types/Todo.d.ts
declare type Todo = {
value: string;
id: number;
checked: boolean;
removed: boolean;
};
src/@types/Filter.d.tsdeclare type Filter = 'all' | 'checked' | 'unchecked' | 'removed';
src/@types/State.d.tsdeclare type State = {
text: string;
todos: Todo[];
filter: Filter;
};
4. 상태의 초기 값 설정
위의 유형 정의를 사용하여 각 상태의 초기 값을 설정합니다.
src/initialState.ts
export const initialState: State = {
text: '',
todos: [],
filter: 'all',
};
5. 액션의 필요조건 논의
이전 TODO 응용 프로그램에서 상태를 업데이트하는 콜백 함수는 다음 7개입니다.
handleOnChange: (e: Event) => void;
handleOnFilter: (e: Event) => void;
handleOnSubmit: () => void;
handleOnEmpty: () => void;
handleOnEdit: (id: number, value: string) => void;
handleOnCheck: (id: number, checked: boolean) => void;
handleOnRemove: (id: number, removed: boolean) => void;
이 7개의 교체action
를 맞추어라.handle On Change 및 handle On Filter
src/@types/Action.d.ts
declare type Action =
| { type: 'change'; text: string }
| { type: 'filter'; filter: Filter };
handleOn Submit 및 handleOn Entery 추가
src/@types/Action.d.ts
declare type Action =
| { type: 'change'; text: string }
| { type: 'filter'; filter: Filter }
| { type: 'submit' }
| { type: 'empty' };
handleOn Edit, handleOn Check, handleOn Remove 추가
src/@types/Action.d.ts
declare type Action =
| { type: 'change'; text: string }
| { type: 'filter'; filter: Filter }
| { type: 'submit' }
| { type: 'empty' }
| { type: 'edit'; id: number; value: string }
| { type: 'check'; id: number; checked: boolean }
| { type: 'remove'; id: number; removed: boolean };
6. 업데이트 상태를 만드는 Reducter 방법
reducter 방법의 유형
(state: State, action: Action) => newState: State
수신State
형과 Action
형을 매개 변수로 하고 새로운 상태로 되돌려줍니다.이루어지다
src/reducer.ts
const reducer = (state: State, action: Action): State => {};
상기 7개의 호출 함수를 Action
에 넣으세요.src/reducer.ts
export const reducer = (state: State, action: Action): State => {
switch (action.type) {
case 'change': {
return { ...state, text: action.text };
}
case 'check': {
const deepCopy = state.todos.map((todo) => ({ ...todo }));
const newTodos = deepCopy.map((todo) => {
if (todo.id === action.id) {
todo.checked = !action.checked;
}
return todo;
});
return { ...state, todos: newTodos };
}
case 'edit': {
const deepCopy = state.todos.map((todo) => ({ ...todo }));
const newTodos = deepCopy.map((todo) => {
if (todo.id === action.id) {
todo.value = action.value;
}
return todo;
});
return { ...state, todos: newTodos };
}
case 'empty': {
const newTodos = state.todos.filter((todo) => !todo.removed);
return { ...state, todos: newTodos };
}
case 'filter': {
return { ...state, filter: action.filter };
}
case 'remove': {
const deepCopy = state.todos.map((todo) => ({ ...todo }));
const newTodos = deepCopy.map((todo) => {
if (todo.id === action.id) {
todo.removed = !action.removed;
}
return todo;
});
return { ...state, todos: newTodos };
}
case 'submit': {
if (!state.text) return state;
const newTodo: Todo = {
value: state.text,
id: new Date().getTime(),
checked: false,
removed: false,
};
return { ...state, todos: [newTodo, ...state.todos], text: '' };
}
default: {
return state;
}
}
};
7.useState를useReducer로 교체
useReducer
등 가져오기:src/index.tsx
- import { useState } from 'react';
+ import { useReducer } from 'react';
+ import { reducer } from './reducer';
+ import { initialState } from './initialState';
useState
연결을 삭제하고 reducer
방법과 초기 상태에 따라 창설state
과dispatch
.src/index.tsx
const App = () => {
const [state, dispatch] = useReducer(reducer, initialState);
8. 호출 함수 7개의 setHoge를 dispatch로 대체
handleOnChage
const handleOnChange = (e: React.ChangeEvent<HTMLInputElement>) => {
dispatch({ type: 'change', text: e.target.value });
};
handleOnSubmit
const handleOnSubmit = () => {
dispatch({ type: 'submit' });
};
handleOnEdit
const handleOnEdit = (id: number, value: string) => {
dispatch({ type: 'edit', id, value });
};
handleOnCheck
const handleOnCheck = (id: number, checked: boolean) => {
dispatch({ type: 'check', id, checked });
};
handleOnRemove
const handleOnRemove = (id: number, removed: boolean) => {
dispatch({ type: 'remove', id, removed });
};
handleOnEmpty
const handleOnEmpty = () => {
dispatch({ type: 'empty' });
};
handleOnFilter
const handleOnFilter = (e: React.ChangeEvent<HTMLSelectElement>) => {
dispatch({ type: 'filter', value: e.target.value as Filter });
};
9. 함수 내 또는 JSX 내 참조 상태의 일부statehoge로 수정
src/index.tsx
const filteredTodos = state.todos.filter((todo) => {
switch (state.filter) {
case 'all':
return !todo.removed;
case 'checked':
return todo.checked && !todo.removed;
case 'unchecked':
return !todo.checked && !todo.removed;
case 'removed':
return todo.removed;
default:
return todo;
}
});
return (
<div>
<select defaultValue="all" onChange={handleOnFilter}>
<option value="all">すべてのタスク</option>
<option value="checked">完了したタスク</option>
<option value="unchecked">現在のタスク</option>
<option value="removed">ごみ箱</option>
</select>
{state.filter === 'removed' ? (
<button
onClick={handleOnEmpty}
disabled={state.todos.filter((todo) => todo.removed).length === 0}
>
ゴミ箱を空にする
</button>
) : (
<form
onSubmit={(e) => {
e.preventDefault();
handleOnSubmit();
}}
>
<input
type="text"
value={state.text}
disabled={state.filter === 'checked'}
onChange={(e) => handleOnChange(e)}
/>
<input
type="submit"
value="追加"
disabled={state.filter === 'checked'}
onSubmit={handleOnSubmit}
/>
</form>
)}
<ul>
{filteredTodos.map((todo) => {
return (
<li key={todo.id}>
<input
type="checkbox"
disabled={todo.removed}
checked={todo.checked}
onChange={() => handleOnCheck(todo.id, todo.checked)}
/>
<input
type="text"
disabled={todo.checked || todo.removed}
value={todo.value}
onChange={(e) => handleOnEdit(todo.id, e.target.value)}
/>
<button onClick={() => handleOnRemove(todo.id, todo.removed)}>
{todo.removed ? '復元' : '削除'}
</button>
</li>
);
})}
</ul>
</div>
);
10. 각 부분을 구성 요소로 잘라서 메모화
memo
화하면props가 변하지 않으면 다시 계산하지 않기 때문에 성능이 향상될 수 있음dispatch
를props로 전달하거나 각 구성 요소에서 상태 업데이트state
도props로 수신Selector 구성 요소
src/Selector.tsx
import { Dispatch, memo } from 'react';
type Props = {
dispatch: Dispatch<Action>;
};
export const Selector = memo((props: Props) => {
const handleOnFilter = (e: React.ChangeEvent<HTMLSelectElement>) => {
props.dispatch({ type: 'filter', filter: e.target.value as Filter });
};
return (
<select defaultValue="all" onChange={handleOnFilter}>
<option value="all">すべてのタスク</option>
<option value="checked">完了したタスク</option>
<option value="unchecked">現在のタスク</option>
<option value="removed">ごみ箱</option>
</select>
);
});
Selector.displayName = 'Selector';
구성 요소
src/EmptyButton.tsx
import { Dispatch, memo } from 'react';
type Props = {
dispatch: Dispatch<Action>;
};
export const EmptyButton = memo((props: Props) => {
const handleOnEmpty = () => {
props.dispatch({ type: 'empty' });
};
return <button onClick={handleOnEmpty}>ごみ箱を空にする</button>;
});
EmptyButton.displayName = 'EmptyButton';
Form 구성 요소
src/Form.tsx
import { Dispatch, memo } from 'react';
type Props = {
state: State;
dispatch: Dispatch<Action>;
};
export const Form = memo((props: Props) => {
const handleOnSubmit = () => {
props.dispatch({ type: 'submit' });
};
const handleOnChange = (e: React.ChangeEvent<HTMLInputElement>) => {
props.dispatch({ type: 'change', text: e.target.value });
};
return (
<form
onSubmit={(e) => {
e.preventDefault();
handleOnSubmit();
}}
>
<input
type="text"
disabled={props.state.filter === 'checked'}
value={props.state.text}
onChange={handleOnChange}
/>
<input
type="submit"
disabled={props.state.filter === 'checked'}
value="追加"
onSubmit={handleOnSubmit}
/>
</form>
);
});
Form.displayName = 'Form';
FilteredTodos 구성 요소
src/FilteredTodos.tsx
import { Dispatch, memo } from 'react';
type Props = {
state: State;
dispatch: Dispatch<Action>;
};
export const FilteredTodos = memo((props: Props) => {
const handleOnEdit = (id: number, value: string) => {
props.dispatch({ type: 'edit', id, value });
};
const handleOnCheck = (id: number, checked: boolean) => {
props.dispatch({ type: 'check', id, checked });
};
const handleOnRemove = (id: number, removed: boolean) => {
props.dispatch({ type: 'remove', id, removed });
};
const filteredTodos = props.state.todos.filter((todo) => {
switch (props.state.filter) {
case 'all':
return !todo.removed;
case 'checked':
return !todo.removed && todo.checked;
case 'unchecked':
return !todo.removed && !todo.checked;
case 'removed':
return todo.removed;
default:
return todo;
}
});
return (
<ul>
{filteredTodos.map((todo) => {
return (
<li key={todo.id}>
<input
type="checkbox"
disabled={todo.removed}
checked={todo.checked}
onChange={() => handleOnCheck(todo.id, todo.checked)}
/>
<input
type="text"
disabled={todo.checked || todo.removed}
value={todo.value}
onChange={(e) => handleOnEdit(todo.id, e.target.value)}
/>
<button onClick={() => handleOnRemove(todo.id, todo.removed)}>
{todo.removed ? '復元' : '削除'}
</button>
</li>
);
})}
</ul>
);
});
FilteredTodos.displayName = 'FilteredTodos';
모듈
src/index.tsx
import { useReducer } from 'react';
import './App.scss';
import { reducer } from './reducer';
import { initialState } from './initialState';
import { Form } from './Form';
import { Selector } from './Selector';
import { EmptyButton } from './EmptyButton';
import { FilteredTodos } from './FilteredTodos';
export const App = (): JSX.Element => {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<Selector dispatch={dispatch} />
{state.filter === 'removed' ? (
<EmptyButton dispatch={dispatch} />
) : (
<Form state={state} dispatch={dispatch} />
)}
<FilteredTodos state={state} dispatch={dispatch} />
</div>
);
};
지금까지 TODO였습니다.
useContext 가져오기
전형적인 React 응용 프로그램에서 데이터는 프롬프트를 통해 아버지에서 아들로 이동하고 손자에게 차례로 전달된다.그러나
useContext
갈고리를 사용하면 나무의 각 단계에서 속성을 현저하게 전달하지 않고 구성 요소 간에 이 값을 공유할 수 있다.이미지 참조 소스: React hooks(useContext 편) 이해
1. 컨텍스트 작성
createContext 구문
const MyContext = React.createContext(defaultValue);
AppContext 만들기
여기에 전항에서 유지수요
props
로 각 부품에 전달되는 State
와 Dispatch
의 상하문으로 한다.src/AppContext.ts
import { createContext, Dispatch } from 'react';
export const AppContext = createContext(
{} as { state: State; dispatch: Dispatch<Action> }
);
3. Context 공급자(=모 어셈블리)의 설정(1)
return 文
의JSX
용AppContext.Provider
으로 싸주세요.src/index.tsx
+ import { AppContext } from './AppContext';
export const App = (): JSX.Element => {
const [state, dispatch] = useReducer(reducer, initialState);
return (
+ <AppContext.Provider value={{ state, dispatch }}>
+ <div>
<Selector dispatch={dispatch} />
{state.filter === 'removed' ? (
<EmptyButton dispatch={dispatch} />
) : (
<Form state={state} dispatch={dispatch} />
)}
<FilteredTodos state={state} dispatch={dispatch} />
</div>
+ </AppContext.Provider>
);
};
4. Context 공급자(=모 어셈블리)의 설정(2)
기존
props
에서 제공한 AppContext.Provider
의 값이나 state
방법을 대체하기 위해 각 구성 요소의 dispatch
를 삭제합니다.src/index.tsx
return (
<AppContext.Provider value={{ state, dispatch }}>
<div>
<Selector />
{state.filter === 'removed' ? <EmptyButton /> : <Form />}
<FilteredTodos />
</div>
</AppContext.Provider>
);
5.props에서 제공하는 구성 요소의 설정을 수락합니다
Context 구문
컨텍스트 객체(React.createContext에서 반환된 값)를 수신하고 컨텍스트의 현재 값을 반환합니다.
const value = useContext('コンテキストオブジェクト');
useContext
의 매개 변수에 대한 제공useContext フック
을 통해 제공된 상하문(=AppContext
과 State
을 활용할 수 있기 때문에 삭제Dispatch
.Form.tsx
import { memo, useContext } from 'react';
import { AppContext } from './AppContext';
export const Form = memo(() => {
const { state, dispatch } = useContext(AppContext);
const handleOnSubmit = () => {
dispatch({ type: 'submit' });
};
const handleOnChange = (e: React.ChangeEvent<HTMLInputElement>) => {
dispatch({ type: 'change', text: e.target.value });
};
return (
<form
onSubmit={(e) => {
e.preventDefault();
handleOnSubmit();
}}
>
<input
type="text"
disabled={state.filter === 'checked'}
value={state.text}
onChange={handleOnChange}
/>
<input
type="submit"
disabled={state.filter === 'checked'}
value="追加"
onSubmit={handleOnSubmit}
/>
</form>
);
});
Form.displayName = 'Form';
지금까지 TODO였습니다.
Reference
이 문제에 관하여(TODO 응용 프로그램을 통해use Reducter+useContext에 들어가기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/sprout2000/articles/1b52258b507b70텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)