데이터는 위에서 아래로 흐름(하향식 top-down
) - 단방향
데이터를 전달하는 주체는 부모 컴포넌트이고 props
를 사용해 데이터를 마치 인자(arguments) 혹은 속성(attributes)처럼 전달한다.
컴포넌트는 props
를 통해 전달받은 데이터가 어디서 왔는지 전혀 알지 못하고 전달받은 데이터의 형태 혹은 타입이 무엇인지만 알 수 있다.
변하는 데이터 값은 상태(state
)
=> 상태가 많아질수록 애플리케이션은 복잡해지기 때문에 최소화하는게 Best
부모로부터 props
를 통해 전달되거나 시간이 지나도 변하지 않거나 컴포넌트 안의 다른 state
나 props
를 가지고 계산 가능하면 상태(state
)가 아니다.
두 개의 자식 컴포넌트가 하나의 상태에 접근하고자 할 때는 두 자식의 공통의 부모 컴포넌트에 상태를 위치한다.
자식의 상태가 부모의 상태에 영향을 끼칠 때 역방향 데이터 흐름 같아 보이지만 상태(state) 끌어 올리기를 통해 단방향 데이터 흐름 원칙에 부합한다.
상태 끌어 올리기에서는 상태 변경 함수가 정의된 컴포넌트와 상태 변경 함수를 호출하는 컴포넌트가 다르다.
=> 상태를 변경시키는 함수(handler)를 하위 컴포넌트에 props로 전달하고 이 함수를 하위 컴포넌트가 실행한다.
함수 내부에서 어떤 구현이 함수 외부에 영향을 끼치는 경우 해당 함수는 Side Effect
가 있다.
Side Effect와 반대되는 순수 함수는 오직 함수의 입력만이 함수의 결과에 영향을 주는 함수를 의미하고 입력으로 전달된 값을 수정하지 않는다.
순수 함수의 특징 중 하나는 어떠한 전달 인자가 주어질 경우 항상 똑같은 값이 리턴됨을 보장해서 예측 가능한 함수이다.
fetch API
를 사용한 AJAX
요청LocalStorage
또는 타이머와 같은 React와 상관없는 APIuseEffect
는 컴포넌트 내에서 Side effect
를 실행할 수 있게 하는 Hook
useEffect
의 첫번째 인자는 함수이고 해당 함수 내에서 side effect를 실행
실행 조건
props
가 전달되며 렌더링state
)가 바뀌며 렌더링이와 같이 매 번 새롭게 컴포넌트가 렌더링될 때 Effect Hook
이 실행됨
Hook 사용 주의사항
Hook
을 호출Hook
을 호출useEffect
의 두번째 인자인 배열의 조건은 boolean 형태의 표현식이 아닌 어떤 값의 변경이 일어날 때를 의미하고 해당 배열엔 어떤 값의 목록이 들어가고 이 배열을 종속성 배열이라한다.
useEffect(함수, [종속성1, 종속성2, ...])
배열 내의 종속성1, 또는 종속성2의 값이 변할 때 첫번째 인자의 함수가 실행
=> 배열 내의 어떤 값이 변할 때에만 (effect가 발생하는) 함수가 실행됨
useEffect
의 두번째 인자인 종속성 배열에 따른 결과
종속성 배열이 빈 배열 일 때 : useEffect(함수, [])
컴포넌트가 처음 생성될때만 effect 함수가 실행됨
=> 처음 단 한번 외부 API를 통해 리소스를 받아오고 더이상 API 호출이 필요하지 않을 때에 사용
종속성 배열이 없을 때 : useEffect(함수)
기본 형태의 useEffect
는 컴포넌트가 처음 생성되거나 props
가 업데이트되거나 상태(state)가 업데이트될 때 effect 함수가 실행됨
두 방식의 장단점
장점 | 단점 | |
---|---|---|
컴포넌트 내부에서 처리 | HTTP 요청의 빈도를 줄일 수 있다 | 브라우저(클라이언트)의 메모리 상에 많은 데이터를 갖게 되므로 클라이언트의 부담이 늘어난다 |
컴포넌트 외부에서 처리 | 클라이언트가 필터링 구현을 생각하지 않아도 된다 | 빈번한 HTTP 요청이 일어나게 되며 서버가 필터링을 처리하므로 서버가 부담을 가진다 |
AJAX 요청(외부 API 접속)이 매우 느릴 경우
const [isLoading, setIsLoading] = useState(true);
return {isLoading ? <LoadingIndicator /> : <div>로딩 완료 화면</div>}
useEffect(() => {
setIsLoading(true);
fetch(`API Endpoint?q=${filter}`)
.then(resp => resp.json())
.then(result => {
setProverbs(result);
setIsLoading(false);
});
}, [filter]);
로딩 화면(loading indicator)의 구현은 필수적이며 로딩 화면 구현도 상태 처리 필요