useState와 use Reducter는 사실상 큰 차이가 있어요.
71743 단어 Next.jsReact.jsTypeScripttech
개시하다
도쿄도 내에서 엔지니어로 개발하다.
구체적인 기술 창고는 다음과 같다.
React.js
의Hooks
와useState
의 차이에 대해 여러 가지 설명을 드리겠습니다.제가 이 기사를 쓴 계기가 되고 싶어요.
지금까지 저는
useReducer
를 이용하여 기본적으로 개발하고 처리useState
의 기회가 없습니다.useReducer
로 복잡한 화면을 설치하면 품질을 보장할 수 없기 때문에 버그가 발생했습니다.(나는 작가의 실장 능력이 부족하다고 생각한다.)그러나 같은 화면
useState
을 다시 쓰면서 품질을 보증할 수 있고, 사회적으로 소개된 것useReducer
과는 다른 장점을 봤기 때문에 보내기로 했다.학습
useReducer
과정React.js
초보자에게는 처리하기 어렵고useReducer
도 같은 처리를 할 수 있기 때문에 많은 분들이 경원하시죠?그런 여러분들.
useState
와useState
의 차이점을 똑똑히 알았다useReducer
사용해 보세요이 문장의 대상
숙지
useReducer
및 React.js
기본 설치이해
TypeScript
의 단어전혀 몰라
単体テスト
와useState
의 큰 차이이번에 만든 기능의 필수 조건.
소개
useReducer
와 useState
를 위해 표를 제작합니다.구체적인 요건은 아래와 같다.
성과물
이번 성과물은
useReducer
에 있다.글에서도 일부분을 소개했으니 여기.에서 실제 동작을 확인해 주십시오
미리 준비하다
codesandbox
및 閲覧モード
구성 요소import React from "react";
type Props = {
index: number;
value: string;
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
onSave: () => void;
onDelete: () => void;
};
export const EditNotificationDestination: React.FC<Props> = ({
index,
value,
onChange,
onSave,
onDelete,
}) => {
return (
<div>
<span>通知先{index}</span>
<input value={value} onChange={onChange} />
<button onClick={onSave}>保存</button>
<button onClick={onDelete}>削除</button>
</div>
);
};
import React from "react";
type Props = {
value: string;
onClick: () => void;
};
export const ViewNotificationDestination: React.FC<Props> = ({
value,
onClick,
}) => {
return (
<div>
<span>{value}</span>
<button onClick={onClick}>編集</button>
</div>
);
};
useState에서 설치
우선
編集モード
.useState
공부를 시작하면 먼저 Hooks를 기억해야 한다.여기를 이용하여 논리를 엮은 것은 다음과 같다.
import React, { useState } from "react";
import { EditNotificationDestination } from "../components/EditNotificationDestination";
import { ViewNotificationDestination } from "../components/ViewNotificationDestination";
import { DisplayMode, NotificationDestination } from "./UseReducer";
export const UseState = () => {
const [notifications, setNotifications] = useState<NotificationDestination[]>(
[]
);
const isNotificationMaximum = notifications.length >= 5;
const changeNotificationDisplayMode = (
index: number,
displayMode: DisplayMode
) => {
const newNotifications = notifications.map((o, mIndex) => {
return index === mIndex ? { displayMode, email: o.email } : o;
});
setNotifications(newNotifications);
};
const addNewNotification = () => {
setNotifications([...notifications, { displayMode: "edit", email: "" }]);
};
const updateNotificationEmail = (
index: number,
e: React.ChangeEvent<HTMLInputElement>
) => {
const newNotifications = notifications.map((o, mIndex) => {
return index === mIndex
? { displayMode: o.displayMode, email: e.target.value }
: o;
});
setNotifications(newNotifications);
};
const deleteNotification = (index: number) => {
const notificationsExcludedIndex = notifications.filter(
(o, fIndex) => index !== fIndex
);
setNotifications(notificationsExcludedIndex);
};
return (
<div className="App">
{notifications.map((o, mIndex) => (
<div key={mIndex}>
{o.displayMode === "edit" ? (
<EditNotificationDestination
index={mIndex + 1}
value={o.email}
onChange={(e) => updateNotificationEmail(mIndex, e)}
onDelete={() => deleteNotification(mIndex)}
onSave={() => changeNotificationDisplayMode(mIndex, "view")}
/>
) : (
<ViewNotificationDestination
value={o.email}
onClick={() => changeNotificationDisplayMode(mIndex, "edit")}
/>
)}
</div>
))}
{!isNotificationMaximum ? (
<button onClick={addNewNotification}>追加</button>
) : null}
</div>
);
};
이것은 흔히 볼 수 있는 실시 방안이다.이것을 파악한 토대
React.js
에서 보자.useReducter에서 설치
다음은
useReducer
를 이용하여 실시한 것이다.UseReducer.tsx
import { EditNotificationDestination } from "../components/EditNotificationDestination";
import { ViewNotificationDestination } from "../components/ViewNotificationDestination";
import { useReducer } from "react";
import { reducer } from "../reducer/reducer";
export type DisplayMode = "view" | "edit";
export type NotificationDestination = {
displayMode: DisplayMode;
email: string;
};
const initialState: NotificationDestination[] = [];
export const UseReducer = () => {
const [notifications, dispatch] = useReducer(reducer, initialState);
const isNotificationMaximum = notifications.length >= 5;
return (
<div className="App">
{notifications.map((o, mIndex) => (
<div key={mIndex}>
{o.displayMode === "edit" ? (
<EditNotificationDestination
index={mIndex + 1}
value={o.email}
onChange={(e) =>
dispatch({
type: "updateNotification",
payload: { index: mIndex, value: e.target.value },
})
}
onDelete={() =>
dispatch({
type: "deleteNotification",
payload: { index: mIndex },
})
}
onSave={() =>
dispatch({
type: "changeDisplayMode",
payload: { index: mIndex, displayMode: "view" },
})
}
/>
) : (
<ViewNotificationDestination
value={o.email}
onClick={() =>
dispatch({
type: "changeDisplayMode",
payload: { index: mIndex, displayMode: "edit" },
})
}
/>
)}
</div>
))}
{!isNotificationMaximum ? (
<button onClick={() => dispatch({ type: "newNotification" })}>
追加
</button>
) : null}
</div>
);
};
reducer.tsimport { NotificationDestination, DisplayMode } from "../pages/UseReducer";
type Actions =
| {
type: "changeDisplayMode";
payload: { index: number; displayMode: DisplayMode };
}
| { type: "newNotification" }
| { type: "updateNotification"; payload: { index: number; value: string } }
| { type: "fetchAllNotification"; payload: { values: string[] } }
| { type: "deleteNotification"; payload: { index: number } };
export const reducer = (
state: NotificationDestination[],
action: Actions
): NotificationDestination[] => {
switch (action.type) {
case "changeDisplayMode": {
const { index, displayMode } = action.payload;
return state.map((o, mIndex) => {
return mIndex === index
? { displayMode: displayMode, email: o.email }
: o;
});
}
case "newNotification": {
return [...state, { displayMode: "edit", email: "" }];
}
case "updateNotification": {
const { index, value } = action.payload;
return state.map((o, mIndex) => {
return mIndex === index
? { displayMode: o.displayMode, email: value }
: o;
});
}
case "fetchAllNotification": {
const { values } = action.payload;
const newState: NotificationDestination[] = values.map((o) => {
return {
displayMode: "view",
email: o,
};
});
return newState;
}
case "deleteNotification": {
const newState: NotificationDestination[] = state.filter(
(o, index) => action.payload.index !== index
);
return newState;
}
}
};
useReducer
의 기본 설치 방법에 관해서는 공식 문서를 참조하십시오.특정
useReducer
에 따라 action
에서 업데이트reducer
를 통해 설치 내용을 쉽게 볼 수 있습니다.use Reducter의 강점은요.
지금까지
state
와 useState
를 실물로 비교했다.useReducer
정의useReducer
,action
이기 때문에 다음과 같은 장점이 있다.reducer
reducer
, 기재해야 하기 때문에action
논리적인 명문화는reducer
보다 더 기재된다useState
이 가장 강하지 않다고 생각한다.그렇다면
useReducer
가장 강한 곳은 무엇일까?여기를 이해하기 위해서 아래 코드를 다시 한 번 봅시다.reducer.ts
export const reducer = (
state: NotificationDestination[],
action: Actions
): NotificationDestination[] => {
switch (action.type) {
case "changeDisplayMode": {
const { index, displayMode } = action.payload;
return state.map((o, mIndex) => {
return mIndex === index
? { displayMode: displayMode, email: o.email }
: o;
});
}
// 以下省略
}
};
자세히 보면 useReducer
수신reducer.ts
과state
의 순함수로 aciton
의useReducer
의state
와는 무관하다.의존하지 않는 순수함수이기 때문에
state
의 논리에 대한 단일 테스트를 쓸 수 있습니다.저자는 복잡한 논리와 복잡한 화면일수록 단일 테스트를 실시할수록 오류를 사전에 방지할 수 있다고 본다.
따라서state와 관련된 단일 테스트를 하는 것은 매우 중요하다.
구체적인 테스트 코드:
reducer.ts
는 다음과 같다.reducer.test.ts
import { reducer } from "./reducer";
import { NotificationDestination } from "../pages/UseReducer";
describe("reducerのテスト", () => {
let notifications: NotificationDestination[] = [
{ displayMode: "view", email: "[email protected]" },
{ displayMode: "view", email: "[email protected]" },
{ displayMode: "view", email: "[email protected]" },
];
beforeEach(() => {
notifications = [
{ displayMode: "view", email: "[email protected]" },
{ displayMode: "view", email: "[email protected]" },
{ displayMode: "view", email: "[email protected]" },
];
});
describe("changeDisplayMode", () => {
it("指定した順番の画面状態が変わる", () => {
const changedNotifications = [
{ displayMode: "view", email: "[email protected]" },
{ displayMode: "edit", email: "[email protected]" },
{ displayMode: "view", email: "[email protected]" },
];
expect(
reducer(notifications, {
type: "changeDisplayMode",
payload: { index: 1, displayMode: "edit" },
})
).toEqual(changedNotifications);
});
it("指定した順番が存在しない場合、状態は変わらない", () => {
const changedNotifications = [
{ displayMode: "view", email: "[email protected]" },
{ displayMode: "view", email: "[email protected]" },
{ displayMode: "view", email: "[email protected]" },
];
expect(
reducer(notifications, {
type: "changeDisplayMode",
payload: { index: -1, displayMode: "edit" },
})
).toEqual(changedNotifications);
});
});
describe("newNotification", () => {
it("連絡先の新規入力項目が追加される", () => {
const addedNotifications = [
{ displayMode: "view", email: "[email protected]" },
{ displayMode: "view", email: "[email protected]" },
{ displayMode: "view", email: "[email protected]" },
{ displayMode: "edit", email: "" },
];
expect(
reducer(notifications, {
type: "newNotification",
})
).toEqual(addedNotifications);
});
});
describe("updateNotification", () => {
it("指定した順番のメールアドレスが変更される", () => {
const updatedNotifications = [
{ displayMode: "view", email: "[email protected]" },
{ displayMode: "view", email: "[email protected]" },
{ displayMode: "view", email: "[email protected]" },
];
expect(
reducer(notifications, {
type: "updateNotification",
payload: { index: 2, value: "[email protected]" },
})
).toEqual(updatedNotifications);
});
it("指定した順番が存在しない場合、状態は変わらない", () => {
const nonUpdatedNotifications = [
{ displayMode: "view", email: "[email protected]" },
{ displayMode: "view", email: "[email protected]" },
{ displayMode: "view", email: "[email protected]" },
];
expect(
reducer(notifications, {
type: "updateNotification",
payload: { index: -1, value: "[email protected]" },
})
).toEqual(nonUpdatedNotifications);
});
});
// 以下省略
});
});
이렇게reducer
는 의존하지 않는 순함수이기 때문에 단독으로 테스트할 수 있다.논리적 관점으로만 묘사하면
useState
과useReducer
가 한 일은 같다.그러나 테스트 측면에서
useReducer
는 단독 테스트가 가능하고useState
는 논리setState
state
에 의존하기 때문에 도저히 쓸 수 없다テストコード
.이 차이는 매우 크다.
useState도 강력한 Hooks라는 점은 변하지 않을 것이다.
화면 요건에 따라 훅스를 구분해서 사용하는 게 중요하다고 생각해요.
총결산
useReducer
공식 문서에 설명된 대로state가 여러 값을 뛰어넘는 복잡한 논리가 있을 때·지난state를 바탕으로 state를 업데이트할 때
이런 상황에서 채택함으로써 확실히 힘을 발휘할 수 있다.
그러나 숨겨진 큰 장점은state에 의존하지 않는 구성으로 단일 테스트를 쓰기 쉽다는 것이다.
state 디자인이 좀 복잡하면
useReducer
, 반대로 화면 구성이 복잡하지 않으면useState
이 좋다.이상은 테스트 관점
useReducer
과 useState
의 차이점이다.
Reference
이 문제에 관하여(useState와 use Reducter는 사실상 큰 차이가 있어요.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/tis1116/articles/8b04672a0221bb텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)