리액트 후크를 사용하여 자기 증가 카운터 구현
코드는 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>
보다 다용도적인 접근방식은 함수를 에 저장하고 새로운 간격을 작성하는 새로운 커스텀훅을 작성하는 것입니다.delay
Dan 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
'programing' 카테고리의 다른 글
cron의 Windows 버전은 무엇입니까? (0) | 2023.04.08 |
---|---|
Json Schema 파일 확장자 (0) | 2023.02.14 |
JSON.stringify() 및 JSON.parse() 사용 시 Date() 관련 문제 (0) | 2023.02.14 |
Oracle: SQL 서버용 Profiler와 같은 쿼리를 추적하는 툴이 있습니까? (0) | 2023.02.14 |
IntelliJ는 그라들을 사용한 Spring Boot 어플리케이션을 종료하지 않습니다. (0) | 2023.02.14 |