React 기능 구성 요소 내에서 클래스 사용
18167 단어 tutorialtypescriptreact
React
는 기능적 접근 방식을 사용하도록 권장하지만 고집이 세서 대신 클래스를 사용하고 싶다면 어떻게 해야 할까요? 글쎄, 당신이 충분히 완고하다면 할 수 있습니다.카운터를 작성한다고 가정하고 클래스를 생각해 봅시다.
export class Counter {
private _value: number;
constructor(initialValue: number) {
this._value = initialValue;
}
public get value(): number {
return this._value;
}
public increment(): void {
this.add(1);
}
public decrement(): void {
this.add(-1);
}
public add(n: number): void {
this._value += n;
console.log(`value changed, new value is: ${this._value}`);
}
}
그런 다음 UI 라이브러리를 선택하고 사용하기로 결정합니다.
import { Counter } from "./counter/Counter.class";
export function App(): JSX.Element {
const c = new Counter(100);
const c2 = new Counter(-200);
return (
<div className="App">
<section>
<button onClick={() => c.decrement()}>decrement</button>
{c.value}
<button onClick={() => c.increment()}>increment</button>
</section>
<section>
<button onClick={() => c2.decrement()}>decrement</button>
{c2.value}
<button onClick={() => c2.increment()}>increment</button>
</section>
</div>
);
}
몇 개의 버튼을 누르고
React
가 UI를 업데이트하지 않는다는 것을 알았지만 콘솔에서는 값이 업데이트되고 있음이 분명합니다. 이제 클래스를 사용자 지정 후크로 전환할 수 있지만 재미가 없습니다.대신 업데이트가 발생하지 않는 이유에 대해 생각해 보겠습니다. 대답은 간단합니다. 소품이 변경되지 않았고 구성 요소 상태가 변경되지 않았으며 구성 요소를 업데이트할 필요가 없습니다. 꽤 합리적입니다. 그래서 우리는 무엇을 할 수 있습니까? 기본적으로 구성 요소를 강제로 다시 렌더링하려면
Counter
클래스 메서드가 필요합니다. 즉, 몇 가지 후크를 사용해야 합니다.React
는 메서드에 대한 데코레이터를 제공하므로 인스턴스 메서드가 실행될 때 구성 요소 다시 렌더링을 트리거하는 사용자 지정 데코레이터를 사용할 수 있습니다.import { useState } from "react";
export function useReactChangeDetection(
target: unknown,
propertyKey: string,
descriptor: PropertyDescriptor
): void {
const [, setState] = useState<string | undefined>();
const originalMethod = descriptor.value;
descriptor.value = function (...args: unknown[]) {
const result = originalMethod.apply(this, args);
setState((prev) => (prev === undefined ? "" : undefined));
return result;
};
}
흥미로운 점은
React
기능 구성 요소 외부에 후크를 사용하거나 다른 후크를 사용할 수 없으므로 데코레이터를 Typescript
클래스에 직접 적용할 수 없으므로 다른 것을 생각해야 합니다.우리의 목표는 후크 데코레이터를
React
클래스에 적용하는 것이므로 우리가 할 수 있는 것은 Counter
클래스를 확장하고 데코레이터를 지정된 메서드 이름에 적용하는 사용자 정의 후크를 작성하는 것입니다. 물론 이를 위해서는 메소드 이름을 추출할 수 있는 제네릭을 작성해야 합니다.export type ClassMethod<T> = {
[P in keyof T]: T[P] extends (...args: any[]) => any ? P : never;
}[keyof T];
이제
Counter
수퍼클래스의 확장된 클래스를 생성하는 후크를 만들 수 있습니다.import { useMemo } from "react";
import { ClassMethod } from "../ClassMethod.model";
import { Counter } from "./Counter.class";
import { useReactChangeDetection } from "./useChangeDetection.hook";
export const useCounterClass = (
method: ClassMethod<Counter>,
value: number
) => {
class UseCounterClass extends Counter {
@useReactChangeDetection
public override [method](n: number): void {
super[method](n);
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
return useMemo(() => new UseCounterClass(value), []);
};
우리가 슈퍼 메서드를 오버라이드하고
Counter
후크로 장식하는 방법에 주목하십시오. 이제 후크 내부에서 사용되므로 완벽하게 괜찮습니다. Counter
를 새 후크로 교체하면 인스턴스화할 때 구성 요소 업데이트를 트리거할 클래스 메서드를 선택할 수도 있습니다.import { useCounterClass } from "./counter";
export function App(): JSX.Element {
const c = useCounterClass("add", 100);
const c2 = useCounterClass("decrement", -200);
return (
<div className="App">
<section>
<button onClick={() => c.decrement()}>decrement</button>
{c.value}
<button onClick={() => c.increment()}>increment</button>
</section>
<section>
<button onClick={() => c2.decrement()}>decrement</button>
{c2.value}
<button onClick={() => c2.increment()}>increment</button>
</section>
</div>
);
}
거기에서 모든 상태는 클래스 인스턴스 내부에 있으며
useReactChangeDetection
업데이트를 존중해야 합니다. 터무니없지 않습니까? :디
Reference
이 문제에 관하여(React 기능 구성 요소 내에서 클래스 사용), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/bwca/using-classes-inside-reacts-functional-components-oj3텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)