이번 게시물에서는 useState 후크 React 앱에서 클로저를 생성하는 방법을 보여드리겠습니다.
클로저가 무엇인지 설명하지 않겠습니다. 이 주제에 대한 리소스가 많고 반복하고 싶지 않기 때문입니다. @imranabdulmalik의 이 기사를 읽어보시길 권합니다.
간단히 말하면 클로저는 (Mozilla에서):
...주위 상태(어휘 환경)에 대한 참조와 함께 묶인(동봉된) 함수의 조합입니다. 즉, 클로저를 사용하면 내부 함수에서 외부 함수 범위에 액세스할 수 있습니다. JavaScript에서는 함수가 생성될 때마다 함수 생성 시.
클로저가 생성됩니다.어휘적 환경이라는 용어에 익숙하지 않은 경우를 대비해 @soumyadey의 이 기사나 이 기사를 읽어보세요.
React 애플리케이션에서는 useState 후크로 생성된 구성 요소 상태에 속하는 변수의 클로저를 실수로 생성할 수 있습니다. 이런 일이 발생하면 오래된 폐쇄 문제에 직면하게 됩니다. 즉, 그 동안 변경되어 더 관련성이 없는 상태의 이전 값을 참조할 때입니다.
저는 setTimeout 메소드의 콜백에서 클로저로 닫힐 수 있는 카운터(상태에 속함)를 증가시키는 것이 주요 목표인 Demo React 애플리케이션을 만들었습니다.
간단히 말하면 이 앱의 기능은 다음과 같습니다.
다음 그림은 카운터가 0인 앱의 초기 UI 상태를 보여줍니다.
카운터 폐쇄를 세 단계로 시뮬레이션합니다.
5초 후 카운터 값은 2입니다.
카운터의 예상 값은 12이어야 하지만 2을 얻습니다.
이런 일이 발생하는 이유는 setTimeout에 전달된 콜백에서 카운터 폐쇄를 생성했고 시간 초과가 트리거될 때 카운터를 다음부터 설정하기 때문입니다. 이전 값(1).
setTimeout(() => { setLogs((l) => [...l, `You closed counter with value: ${counter}\n and now I'll increment by one. Check the state`]) setTimeoutInProgress(false) setStartTimeout(false) setCounter(counter + 1) setLogs((l) => [...l, `Did you create a closure of counter?`]) }, timeOutInSeconds * 1000);
앱 구성 요소의 전체 코드를 따릅니다.
function App() { const [counter, setCounter] = useState(0) const timeOutInSeconds: number = 5 const [startTimeout, setStartTimeout] = useState (false) const [timeoutInProgress, setTimeoutInProgress] = useState (false) const [logs, setLogs] = useState >([]) useEffect(() => { if (startTimeout && !timeoutInProgress) { setTimeoutInProgress(true) setLogs((l) => [...l, `Timeout scheduled in ${timeOutInSeconds} seconds`]) setTimeout(() => { setLogs((l) => [...l, `You closed counter with value: ${counter}\n and now I'll increment by one. Check the state`]) setTimeoutInProgress(false) setStartTimeout(false) setCounter(counter + 1) setLogs((l) => [...l, `Did you create a closure of counter?`]) }, timeOutInSeconds * 1000); } }, [counter, startTimeout, timeoutInProgress]) function renderLogs(): React.ReactNode { const listItems = logs.map((log, index) => {log} ); return{listItems}
; } function updateCounter(value: number) { setCounter(value) setLogs([...logs, `The value of counter is now ${value}`]) } function reset() { setCounter(0) setLogs(["reset done!"]) } return (); } export default App;Closure demo
Counter value: {counter}
Follow the istructions to create a closure of the state variable counter
- Set the counter to preferred value
- Start a timeout and wait for {timeOutInSeconds} to increment the counter (current value is {counter})
- Increment by 10 the counter before the timeout
{ renderLogs() }
이 솔루션은 렌더링에 필요하지 않은 값을 참조할 수 있는 useRef 후크 사용을 기반으로 합니다.
App 구성요소에 다음을 추가합니다.
const currentCounter = useRef(counter)
그런 다음 아래와 같이 setTimeout의 콜백을 수정합니다.
setTimeout(() => { setLogs((l) => [...l, `You closed counter with value: ${currentCounter.current}\n and now I'll increment by one. Check the state`]) setTimeoutInProgress(false) setStartTimeout(false) setCounter(currentCounter.current + 1) setLogs((l) => [...l, `Did you create a closure of counter?`]) }, timeOutInSeconds * 1000);
현재 값을 증가시키기 전에 기록하므로 콜백은 카운터 값을 읽어야 합니다.
값을 읽을 필요가 없는 경우 함수 표기법을 사용하여 카운터를 업데이트하면 카운터가 닫히는 것을 방지할 수 있습니다.
seCounter(c => c + 1)
위 내용은 반응: 오래된 폐쇄의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!