[React]ContextAPI의 역모드
ContextAPI와useState는 원래 조합이 안 돼요.
ContextAPI의 기능은 어셈블리 계층 간에 데이터를 전송하는 것입니다.그러나 여기서 주의해야 할 것은useState로 Provider가 설정한 값을 관리하면 Provider를 가진 모든 트리를 다시 나타낼 수 있다는 것이다.이 작법은 최악의 반모드다.
역모드
고급 구성 요소useState의 스케줄러가 업데이트를 사용하여 Provider에 전달된 값을 사용하고 있습니다.모든 업데이트 값이 업데이트되면 모든 구성 요소가 다시 나타납니다.이러한 방법은 ContextAPI 설명에서 자주 볼 수 있습니다.그러나 한 값의 변경으로 모두 다시 쓰면 상태 관리의 필요성이 사라진다.이것은 해서는 안 되는 서법이다.
import { createContext, useContext, useState } from "react";
type ValueType = { [key: string]: number | undefined };
const context = createContext<ValueType>(undefined as never);
const Component = ({ name }: { name: string }) => {
const value = useContext(context);
console.log(name);
return (
<div>
{name}:{value[name]}
</div>
);
};
const Page = () => {
const [value, setValue] = useState<ValueType>({});
console.log("Main");
return (
<>
<button onClick={() => setValue((v) => ({ ...v, A: (v["A"] || 0) + 1 }))}>
A
</button>
<button onClick={() => setValue((v) => ({ ...v, B: (v["B"] || 0) + 1 }))}>
B
</button>
<button onClick={() => setValue((v) => ({ ...v, C: (v["C"] || 0) + 1 }))}>
C
</button>
<context.Provider value={value}>
<Component name="A" />
<Component name="B" />
<Component name="C" />
</context.Provider>
</>
);
};
export default Page;
Main
A
B
C
불필요한 리메이크를 일으키지 않는 모드
useRef에서 만든 객체를 Provider에 전달합니다.Context 업데이트는 무음판에서 이루어지기 때문에 다시 써도 다시 쓰지 않습니다.다시 쓸 구성 요소는 각각state를 다시 써서 다시 쓸 것을 알립니다.Context가 보유한 데이터는 서브어셈블리 내의 소음기입니다.
이 쓰기 방법에 따라 버튼 A를 누르면 렌더링
<Component name="A" />
만 하면 됩니다.import {
createContext,
Dispatch,
SetStateAction,
useContext,
useEffect,
useRef,
useState,
} from "react";
type ValueType = {
[key: string]: Dispatch<SetStateAction<number | undefined>>;
};
const context = createContext<ValueType>(undefined as never);
const Component = ({ name }: { name: string }) => {
console.log(name);
const [value, setValue] = useState<number>();
const dispatches = useContext(context);
useEffect(() => {
dispatches[name] = setValue;
return () => {
delete dispatches[name];
};
}, [name]);
return (
<div>
{name}:{value}
</div>
);
};
const Page = () => {
console.log("Main");
const dispatches = useRef<ValueType>({}).current;
return (
<>
<button onClick={() => dispatches["A"]?.((v) => (v || 0) + 1)}>A</button>
<button onClick={() => dispatches["B"]?.((v) => (v || 0) + 1)}>B</button>
<button onClick={() => dispatches["C"]?.((v) => (v || 0) + 1)}>C</button>
<context.Provider value={dispatches}>
<Component name="A" />
<Component name="B" />
<Component name="C" />
</context.Provider>
</>
);
};
export default Page;
A
Context 측에 데이터를 보유하도록 하면서 불필요한 렌더링 방지 모드
구조가 좀 복잡하지만 같은 이름의 데이터가 여러 구성 요소에 사용되는 상황에서도 참을 수 있다.Context 측에서 데이터를 저장하는 동시에 렌더링을 촉진하는 모니터도 관리합니다.
그러면 해당 이름의 데이터만 사용하는 어셈블리가 다시 렌더링됩니다.
import {
createContext,
Dispatch,
SetStateAction,
useContext,
useEffect,
useRef,
useState,
} from "react";
type ValueType = {
dispatches: { [key: string]: Set<Dispatch<SetStateAction<{}>>> };
values: { [key: string]: number | undefined };
};
const context = createContext<ValueType>(undefined as never);
const Component = ({ name }: { name: string }) => {
console.log(name);
const [_, setValue] = useState<{}>();
const { values, dispatches } = useContext(context);
useEffect(() => {
if (dispatches[name]) dispatches[name].add(setValue);
else dispatches[name] = new Set([setValue]);
return () => {
dispatches[name].delete(setValue);
};
}, [name]);
return (
<div>
{name}:{values[name]}
</div>
);
};
const Page = () => {
console.log("Main");
const manager = useRef<ValueType>({ dispatches: {}, values: {} }).current;
const { dispatches, values } = manager;
return (
<>
<button
onClick={() => {
values["A"] = (values["A"] || 0) + 1;
dispatches["A"].forEach((v) => v({}));
}}
>
A
</button>
<button
onClick={() => {
values["B"] = (values["B"] || 0) + 1;
dispatches["B"].forEach((v) => v({}));
}}
>
B
</button>
<button
onClick={() => {
values["C"] = (values["C"] || 0) + 1;
dispatches["C"].forEach((v) => v({}));
}}
>
C
</button>
<context.Provider value={manager}>
<Component name="A" />
<Component name="B" />
<Component name="C" />
<Component name="A" />
<Component name="B" />
<Component name="C" />
</context.Provider>
</>
);
};
export default Page;
A
A
총결산
ContextAPI는 Provider 내에서 데이터를 배포하는 데 사용되는 기능입니다.일부는 이상한 오해가 있었지만, 쓸모없는 재렌더링 기능은 절대 아니었다.특정 구성 요소를 재현하도록 재촉할 때, 각 구성 요소 안에서 setState를 하고 스케줄러를 사용합니다.또한 setState의 주요 기능은 재재현 이벤트를 생성하기 위한 것이지 데이터를 저장하는 것이 아니다.데이터를 저장하려면useRef가 올바른 선택입니다.
이번에 해설은 모니터를 벗겨내는 호출로 작성돼 잘 포장하면 사용하기 쉽다.
리액트를 사용할 때 가장 중요한 것은 적절한 시기에 전성기를 부르는 것이다.그것만 할 수 있다면 정음판으로 데이터를 처리하는 것도 전혀 문제가 없다.다시 돋보이는 폭포 수행을 응용 프로그램에 편입하지 않도록 시기를 잘 관리해 주십시오.
Reference
이 문제에 관하여([React]ContextAPI의 역모드), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/sora_kumo/articles/72fae8a8244adf텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)