render()
를 제외한 나머지 method 및 state는 그대로 보존이 되어 있음.Stateless Component
라고 했던 것.state
만을 의미하는 것이 아닌, 함수내에 써져 있는 모든 코드 및 변수를 기억할 수 없다는 의미state
를 Function Component에서 사용하게 해주는 Hookthis.state
와 this.setState
를 대체const [value, setValue] = useState(0);
useState(param)
의 parameter : value의 초깃값 설정useState(param)
의 반환 값 : 배열this.setState()
) 와 유사 ) useState((prev)=> prev+1); // number
useState((prev)=> {...prev, newID: newValue}) // object
useState((prve)=> [...prev, newValue]) // array
useState
는 이전 state
값을 인자로 자동으로 받아오는 callback function을 인자로 넣을 수 있음.useCallback
, useMemo
에서 성능 최적화 작업 // state의 값이 바뀐다고, useCallback이나 useMemo를 다시 할당할 이유가 없음.
// 그러나 아래와 같이 함수형 업데이트를 사용하지 않으면, 반드시 재할당해야함
// 이전 state 값을 자체적으로 가지고 있기 때문
const onChange = useCallback(e=> {
const {name, value} = e.target;
setUser({
...user,
name: value,
})
}, [user]); // 반드시 두번째 인자로 user를 넘겨줘야함
// 함수형 업데이트에서는 setState자체에서 이전 state값을 가져옴
// 따라서 dependency로 넘겨주지 않아도 되고
// state가 갱신될때 마다 해당 Hook을 재할당하지 않아도 됨
const onChange = useCallback(e=> {
setUser((prev)=>{
const {name, value} = e.target;
return {
...prev,
name: value,
};
})
}, []); // 더이상 user 관련하여 재할당하지 않음
// 아래와 같이 아예 다른 state값을 할당해야 한다면
// 함수형 업데이트는 필요하지 않을 수도 있음.
const onChangeName = (event) => {
const newName = event.currentTarget.value;
setName(newName);
};
// 하지만 대다수의 state (특히 객체와 배열) 는 이전 상태가 필요함.
// 이 경우 함수형 업데이트가 필요함
const onAddUser = (event) => {
setUser((prev)=>{
const newUser = event.currentTarget.value;
return [...prev,newUser];
})
}
setState
관련 로직이 좀 더 깔끔해짐state
와 관련된 모든 로직을 setState
안에 넣기 때문 // not good, 깔끔하지 못한 setState
const onClick = () =>{
const newId = 3;
const newValue = "안녕하세요";
setState({
...state,
newID: newValue,
})
}
// good, 새로운 state와 관련된 모든 로직이 setState안에 들어있어서 구분이 깔끔함
const onClick = () => {
setState((prev)=>{
const newId = 3;
const newValue = "안녕하세요";
return {...prev, newID: newValue};
}
}
setValue
를 쓴다고 즉각적으로 바뀌지 않음 (비동기적)state
를 이용하는 로직을 짜야하는 경우 반드시 useEffect
에서 처리할 것!! // bad code, count와 관련된 뒷처리 코드를 onClick에서 다 처리
const onClick = () => {
setState(count+1);
if(count===3) alret("3 입니다!");
}
// good code, onClick에서는 state의 갱신만, 뒷처리 코드는 useEffect에서 처리
useEffect(()=>{
if(count===3) alert("3 입니다!");
})
const onClick = () => {
setState(count+1);
}
⇒ `useEffect` 가 존재하는 이유이기도 함.
setValue
에서 반드시 immutable 을 지켜서, 새롭게 할당한 변수를 넘겨줘야함state
가 바뀌는 것을 감지할때 shallow Comparison을 이용하기 때문.[...]
or {...}
)componentDidMount
, componentDidUpdate
, componentWillUnmount
를 대체useEffect(() => {
console.log('렌더링이 완료되었습니다!');
},[]);
useEffect
의 첫번째 parameter : rendering이 될때 실행시킬 함수 (callback)useEffect
가 실행될때 이전의 state값을 가지고 먼저 실행되게 되어 있음componentWillUnmount
와 같은 포지션 useEffect(() => {
console.log('effect');
console.log(name);
return () => {
console.log('cleanup');
console.log(name);
};
});
useEffect
가 동작하는 순서는 총 순서는 다음과 같다.useEffect
의 두번째 parameter : 배열 (dependency array)useState()
로 지정한 변수나 props
componentDidMount
일 때만 실행 (최초 랜더링시에만) useEffect(() => {
console.log('마운트 될 때만 실행됩니다.');
}, []);
useEffect(() => {
console.log(name);
}, [name]); // name이 바뀔때만 실행됨
useEffect
가 실행될 수 있게끔.useEffect
분리하기 // bad, 모든 sideEffect를 하나의 useEffect에 넣음
useEffect(()=>{
if (user.length==3) alert("3명의 유저가 있어요!");
if (sumbit === true) formRef.reset();
}, [user,submit]); // user와 submit 2개의 dependency를 넣을 수 밖에 없음
// good, useEffect의 로직별 분리
useEffect(()=>{
if(user.length===3) alert("3명의 유저가 있어요!");
},[user]);
useEffect(()=>{
if(submit === true) formRef.reset();
},[submit]);
useEffect
가 써져있는 경우, 위에서 부터 실행됨.React.createRef
를 대체function Sample() {
const btnRef = useRef();
const onClick=()=>{
btnRef.style.color="blue";
};
return (
<div>Ref 예제</div>
<button
onClick={onClick}
ref={btnRef}
/>
)
}
const onClick = useCallback((e)=>{
setState((prev)=>prev+1);
}, []);
useEffect
와 동일하게, 해당 array안에 들어있는 것이 바뀔때만 함수를 재할당함setState
를 함수안에 사용할 경우 함수형 업데이트를 사용할 것.useCallback
을 이용할것React.memo
등으로 최적화를 진행했을때, 정상적으로 작동하기 때문.useCallback
과 동일한 효과const userLength = useMemo(()=>{
console.log("memo 재 할당!);
return user.length;
}, [user]);
useEffect
와 동일하게, 해당 array안에 들어있는 것이 바뀔때만 함수를 재할당함setState
를 연산된 값 안에 사용할 경우 함수형 업데이트를 사용할 것.function FriendStatusWithCounter(props) {
// 이 부분은 몇번이나 클릭했는지를 나타내는 부분!
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
});
// 이 부분은 Server와의 송수신과 관련된 부분!
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
// ...
}
⇒ 위 3가지 사항이 React가 View Library로서 성능을 최적화에 관여하는 규칙이라고 볼 수 있다.
(물론 내가 공부하면서 만든거다.)
잘 읽었습니다. 유익한 시간이었습니다. 좋은 하루 보내세요.