1.Side-effect
import React, { Fragment, useEffect, useState } from "react";
import { Promise } from "bluebird";
Promise.config({ cancellation: true });
function fetchUser() {
return new Promise(resolve => {
setTimeout(() => {
resolve({ id: 1, name: "Adam" });
}, 1000);
});
}
export default function User() {
const [id, setId] = useState("loading...");
const [name, setName] = useState("loading...");
useEffect(() => {
const promise = fetchUser().then(user => {
setId(user.id);
setName(user.name);
});
return () => {
promise.cancel();
};
});
return (
<Fragment>
<p>ID: {id}</p>
<p>Name: {name}</p>
</Fragment>
);
}
UseEffect 는 Lifecycle 대신에 사용할 수 있는 Hook 의 기능이다. UseEffect의 function 은 component 의 rendering 이 완성 된 뒤에 call되어서 Coponent Rendering 되기 전에 data의 fetch 가 되어서 발생할 수 있는 에러를 방지해준다.
UseEffect 말고도 또 체크해야 할 부분이 있는데, 바로 promise cancel 부분이다.
2.promise cancel
useEffect(() => { const promise = fetchUser().then(user => {
setId(user.id); setName(user.name); });
return () => { promise.cancel(); };
});
useEffect 로 Component 가 Mount 될때 fetchUser를 실행해서 사용자 정보를 불러오는 도중, 다른 화면을 가는 등의 행동을 통해 Component 가 UnMount 된다면 Api는 그대로 실행되고, 변경할 state 값이 없어서 에러가 난다. 쓰레드의 자원 관리와 에러 방지를 위해, return()=>{promise.cancel()} 을 통해 Component 가 Unmound 되면 Api Call 을 취소할 수 있다.
3.promise clean
const [resolved, setResolved] = useState(false); useEffect(() => { // ...the effect code... return () => { // ...the cleanup code that depends on "resolved" } }, [resolved]);
const [resolved, setResolved] = useState(false);
useEffect(() => { // ...the effect code...
return () => { /
/ ...the cleanup code that depends on "resolved" } },
[resolved]);
resolved 를 clean으로 호출하면 결과값이 나올때 마다 clean 된다. 만일 resolve의 값이 변하지 않으면 clean이 호출되지 않는다.
만일 Component 가 처음 Mount 될때만 FechApiData를 하고 싶다면 [], Empty Array 를 주면 된다.
useEffect(() => {
const promise = fetchUser().then(user => {
setId(user.id);
setName(user.name);
});
return () => {
promise.cancel();
};
}, []);
만일 []를 지운다면, fechUser 가 여러번 불려지는 걸 알 수 있다. 이건 state가 render 될 때마다 fetch가 실행되어서 그렇다. 처음 state 의 초기값이 loading 이었다가 1초 뒤에 각각 set된 값으로 변경되고 re-render가 되어서 다시 fechdata가 불려진다. state 값이 2개니 2번 rerender 되고 fetchUser는 총 3번 불려지는 것이다.
만일 setState가 하나라면,
const promise = fetchUser().then(user => { setId(user.id); });
1번 re-render 되기 때문에 총 2번 fechUser가 호출된다.
한번만 render 될때마다 다시 호출되는 것이 아닌 한번 호출은 []을 통해 clean 을 해주는 것이 좋다.