import React,{useState,useEffect,useRef} from 'react'
export default function App(){
const [name,setName]=useState('')
// const [renderCount,setRenderCount]=useState(0)
=> useRef로 바꿔보자
const renderCount=useRef(1)
=> renderCount는 current 프로퍼티를 갖는 object다. current property를 업데이트하면 다른 renders 사이에서 변화하지 않고 지속하려는 특성을 가진다.
useEffect(()=>{
// setRenderCount(prevRenderCount => prevRenderCount +1)
renderCount.current =renderCount.current +1
})
return (
<>
<input value={name} onChange={e =>setName(e.target.value)}/>
<div> My name is {name} </div>
<div> I rendered {renderCount.current} times </div>
</>
)
}
state를 업데이트하면 컴포넌트는 re-render가 된다. 위 useEffect의 setRenderCount는 infinite loop에 빠지게 된다.
여기서 알아야 하는 것이 useRef
, Ref는 state와 매우 비슷하다. 이것은 컴포넌트가 re update되지 않게 한다.
인풋 안에 이름을 kdd라고 입력했다. 그러면 I rendered 3 times라고 나올 것이다.
가장 중요하게 알아야 할 것은 useEffect안renderCount.current
를 원하는 만큼 변경할 수 있다는 것이다. 이렇게 변경해도 절대 컴포넌트는 re-render되지 않는다는 것이 핵심!!!
export default function App(){
const [name,setName]=useState('')
const inputRef=useRef()
function focus(){
inputRef.currnet.focus()
}
return (
<>
<input ref={inputRef} value={name} onChange={e =>setName(e.target.value)}/>
<div> My name is {name} </div>
<button onClick={focus}>Focus</button>
</>
)
}
button에 onclick줘서 focus함수 실행시킨다. inputRef.current.focus()를 실행시키면 input textbox가 focus된다.
state는 말 그대로 현재 상태를 말하는 것이기에 이전 값을 저장할 수는 없는데, ref는 이전 값을 저장할 수 있다.
export default function App(){
const [name,setName]=useState('')
const prevName=useRef('')
useEffect(()=>{
prevName.current=name
},[name])
return (
<>
<input value={name} onChange={e =>setName(e.target.value)}/>
<div> My name is {name} and it used to be {prevName.current} </div>
</>
)
}
ref안에 name의 이전 값을 저장하고 싶다.
위와 같이 작성하면 어떤 일이 일어날까?
인풋 창에 a를 먼저입력하고 b를 추가 입력해서 ab가 되게했다.
=> My name is ab
and it used to be a
만약에 useRef가 아닌 useState를 사용했다면 컴포넌트는 re-render되었을 것이다. useRef를 사용하면 불필요한 렌더를 막을 수 있다.