react에서 useState와 useCallback 사용

배경



react로 이런 일을 실현하고 싶습니다.



글쎄, 버튼을 누르면 숫자가 증가하는 사람입니다.
일본에서는 vue가 고조되고 있습니다만, react도 고조되고 싶으면...!
별로 일본어 문헌이 없기 때문에 써 갑니다.

react16.8에서 추가 된 Hook을 사용하여 만들어 봅시다.
typescript로 작성합니다.

안되는 예 1


// Sample.tsx
import React, { useState } from "react";

const Sample = () => {
  const [count, setCount] = useState(0);
  return (
    <div>
      <button
        onClick={() => {
          setCount(count + 1);
        }}
      >
        click here!
      </button>
      <p>count: {count}</p>
    </div>
  );
};
export default Sample;

이렇게하면 tslint에서 다음과 같은 경고가 발생합니다.

Lambdas are forbidden in JSX attributes due to their rendering performance impact (jsx-no-lambda)렌더링시의 퍼포먼스가 좋지 않기 때문에, jsx(확장자는 .tsx입니다만) 속에서 lambda를 쓰지 말아라, 라고 말하고 있습니다.
이렇게 쓰면 렌더링 할 때마다이 함수가 새로 선언되어 버리므로 낭비가 발생합니다.

안되는 예 2



조금 다시 작성해 봅시다.
import React, { useState } from "react";

const Sample = () => {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <button onClick={handleClick}>click here!</button>
      <p>count: {count}</p>
    </div>
  );
};
export default Sample;
onClick 의 처리 부분을 handleClick 로 잘라 보았습니다.
이제 tslint에서 화가 나지 않습니다.
하지만 이것이라도 역시 handleClick 가 렌더링할 때마다 선언되어 버립니다.
이 기사 이나, 이 stackoverflow의 답변 에 써 있습니다.

좋지만 귀찮은 예 → 안돼.



글쎄, 그럼 더 다시 써 봅시다.
import React, { useState } from "react";

const handleClick = (
  count: number,
  setCount: React.Dispatch<React.SetStateAction<number>>
) => () => {
  setCount(count + 1);
};

const Sample = () => {
  const [count, setCount] = useState(0);

  return (
    <div>
      <button onClick={handleClick(count, setCount)}>click here!</button>
      <p>count: {count}</p>
    </div>
  );
};
export default Sample;

이번에는 handleClick의 함수 선언을 Sample 밖으로 내 보았습니다.
이제 렌더링할 때마다 선언되는 문제가 해결됩니다. → 해결되지 않는 것 같습니다 ...

하지만 무엇입니까,이 overkill감.
typescript라고 하는 것도 함께, 단순히 인크리먼트시키고 싶을 뿐인데 기술량이 반단 없다...울음

덧붙여서 필자는 계속 이것으로 쓰고 있었습니다, 상기에서도 소개했다 이 기사 를 만날 때까지는.

useCallback을 함께 사용 → 아직 안됨



밖에 내면 선언이 귀찮습니다. 가능하면 함수 안에 써서 스코프의 혜택을 받으면서, 렌더링시에 재정의하지 않게 하고 싶다. . .
그런 일을 할 수 없다고 생각했습니다.
전혀 할 수 있었습니다.
useCallback 이라는 후크를 사용합시다.
import React, { useState, useCallback } from "react";

const Sample = () => {
  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    setCount(count + 1);
  }, [count]);

  return (
    <div>
      <button onClick={handleClick}>click here!</button>
      <p>count: {count}</p>
    </div>
  );
};
export default Sample;

다만, 이대로와 count가 갱신될 때마다 정의되어 버립니다

useCallback을 함께 사용 → OK 버전


import React, { useState, useCallback } from "react";

const Sample = () => {
  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    setCount(prev => prev + 1);
  }, []);

  return (
    <div>
      <button onClick={handleClick}>click here!</button>
      <p>count: {count}</p>
    </div>
  );
};
export default Sample;

최고군요, 엄청 깨끗이.
더 빨리 알고 싶었습니다 ... 독학의 괴로움입니다.

그건 그렇고, useCallback와 비슷한 것에는 useMemo가 있습니다.
이러한 차이에 관해서는 이 기사 를 알기 쉽습니다.

누군가의 참고가 되시면 다행입니다.

좋은 웹페이지 즐겨찾기