programing

리액트 후크를 사용하여 자기 증가 카운터 구현

firstcheck 2023. 2. 14. 22:36
반응형

리액트 후크를 사용하여 자기 증가 카운터 구현

코드는 https://codesandbox.io/s/nw4jym4n0 입니다.

export default ({ name }: Props) => {
  const [counter, setCounter] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setCounter(counter + 1);
    }, 1000);

    return () => {
      clearInterval(interval);
    };
  });

  return <h1>{counter}</h1>;
};

문제는 각각이다.setCounter트리거 재실행하여 간격이 리셋되고 다시 생성됩니다.상태(카운터)가 계속 증가하기 때문에 정상으로 보이지만 다른 훅과 결합하면 프리즈될 수 있습니다.

올바른 방법은 무엇입니까?클래스 컴포넌트에서는 instance 변수가 간격을 유지하는 것으로 간단합니다.

빈 어레이를 두 번째 인수로 지정할 수 있습니다.useEffect이 기능을 초기 렌더링 후에 한 번만 실행할 수 있도록 합니다.폐쇄가 작동하는 방식 때문에, 이것은 이 모든 것을counter변수는 항상 초기값을 참조합니다.그런 다음 의 기능 버전을 사용할 수 있습니다.setCounter항상 올바른 값을 얻을 수 있습니다.

const { useState, useEffect } = React;

function App() {
  const [counter, setCounter] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setCounter(counter => counter + 1);
    }, 1000);

    return () => {
      clearInterval(interval);
    };
  }, []);

  return <h1>{counter}</h1>;
};

ReactDOM.render(
  <App />,
  document.getElementById('root')
);
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="root"></div>

보다 다용도적인 접근방식은 함수를 에 저장하고 새로운 간격을 작성하는 새로운 커스텀훅을 작성하는 것입니다.delayDan Abramov가 훌륭한 블로그 투고 「Making setInterval Declarative with React Hooks에서 하고 있는 처럼, 변화할 것입니다.

const { useState, useEffect, useRef } = React;

function useInterval(callback, delay) {
  const savedCallback = useRef();

  // Remember the latest callback.
  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  // Set up the interval.
  useEffect(() => {
    let id = setInterval(() => {
      savedCallback.current();
    }, delay);
    return () => clearInterval(id);
  }, [delay]);
}

function App() {
  const [counter, setCounter] = useState(0);

  useInterval(() => {
    setCounter(counter + 1);
  }, 1000);

  return <h1>{counter}</h1>;
};

ReactDOM.render(
  <App />,
  document.getElementById('root')
);
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="root"></div>

@YangshunTay의 다른 답변에서 알 수 있듯이 만들 수 있습니다.useEffect콜백은 1회만 실행되며 와 동일하게 동작합니다.componentDidMount. 이 경우 기능 범위에 따라 제한되므로 상태 업데이트 기능을 사용해야 합니다(그렇지 않으면 업데이트됨).counter내부에서는 사용할 수 없습니다.setInterval콜백

대안은 만드는 것이다.useEffect콜백은 각 카운터 업데이트에서 실행됩니다.이 경우setInterval로 대체해야 한다.setTimeout및 업데이트는 로 제한해야 합니다.counter업데이트:

export default ({ name }: Props) => {
  const [counter, setCounter] = useState(0);

  useEffect(() => {
    const timeout = setTimeout(() => {
      setCounter(counter + 1);
    }, 1000);

    return () => {
      clearTimeout(timeout);
    };
  }, [counter]);

  return <h1>{counter}</h1>;
};

올바른 방법은 효과를 한 번만 실행하는 것입니다.마운트 중에는 빈 배열을 두 번째 인수로 전달할 수 있기 때문에 효과를 한 번만 실행하면 됩니다.

단, 변경하셔야 합니다.setCounter이전의 가치를 이용하다counter그 이유는 콜백이 에 전달되었기 때문입니다.setInterval의 종료는 에만 액세스합니다.counter첫 번째 렌더링의 변수, 새 렌더링에 대한 액세스 권한이 없습니다.counter다음 렌더링의 값입니다.useEffect().두 번째 호출은 없습니다.counter 、 [ 0 ] 、 [ 0 ] 、 [ ] の [ 0 ]에는 0 의 값이 있습니다.setInterval콜백

setState익숙한 상태 훅에는 갱신된 상태로 이행되는 형식과 현재 상태가 전달되는 콜백 형식의 두 가지 형식이 있습니다.하여 이 의 최신 .setState하여 증가하기 값을 있는지 합니다.callback은 최신 상태 값을 있는지 합니다.

function Counter() {
  const [counter, setCounter] = React.useState(0);
  React.useEffect(() => {
    const timer = setInterval(() => {
      setCounter(prevCount => prevCount + 1); // <-- Change this line!
    }, 1000);
    return () => {
      clearInterval(timer);
    };
  }, []); // Pass in empty array to run effect only once!

  return (
    <div>Count: {counter}</div>
  );
}

ReactDOM.render(<Counter />, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="app"></div>

언급URL : https://stackoverflow.com/questions/53395147/use-react-hook-to-implement-a-self-increment-counter

반응형