React 데이터 흐름

하위 컴포넌트에서 이벤트가 부모의 상태를 바꾸어야 할 때 State 끌어올리기(Lifting state up)

상태를 변경시키는 함수(이벤트 핸들러)를 하위 컴포넌트에 props로 전달해서 해결

https://codesandbox.io/s/twittler-react-lifting-state-up-hooks-ig6n4?from-embed=&file=/src/Twittler.js:1232-1240

https://codesandbox.io/s/simple-lifting-state-up-hooks-ljrdy?from-embed=&file=/src/App.js:284-301

고차함수, 이벤트 사용법, props&state의 이해가 더 필요하다.


onChange - 눌렀다 때었을 때 동작

onKeyPress - 눌렀다 때었을 때 동작 + 누르고 있을 때 연발


Effect Hook

Side Effect(부수효과)


함수 내에서 어떤 구현이 함수 외부에 영향을 끼치는 경우

컴포넌트 내에서 fetch를 사용해 API 정보를 가져오거나 이벤트를 활용해 DOM 직접 조작할 때

Pure Function(순수 함수)


함수의 입력만이 함수의 결과에 영향을 주는 함수

  • Math.random()가 순수 함수가 아닌 이유 - 동일한 입력에도 다른 출력이 나오기 때문

  • 어떤 함수가 fetch API를 이용해 AJAX 요청 이 함수가 순수 함수가 아닌 이유 - 네트워크에 요청을 보냄으로 서버의 데이터에 Side Effect를 일이킬 수 있기 때문

React 컴포넌트에서의 Side Effect


  • 타이머(setTimeout)
  • 데이터 가져오기(fetch API, localStorage)

Effect Hook


React는 Side Effect를 다루기 위한 Hook인 Effect Hook을 제공

useEffect의 첫 번째 인자는 함수, 해당 함수 내에서 side effect

https://codesandbox.io/s/lj4p9?file=/src/App.js

function Proverb({ saying }) {
  useEffect(() => {
    document.title = saying;
  });
  return (
    <div>
      <h3>오늘의 명언</h3>
      <div>{saying}</div>
    </div>
  );
}
  • 컴포넌트 생성 후 처음 화면에 렌더링(표시)
  • 컴포넌트에 새로운 props가 전달되며 렌더링
  • 컴포넌트에 상태(state)가 바뀌며 렌더링(return 문이 아님)

Effect Hook을 컴포넌트 내에서 최초 1회만 호출하고 싶을 때

useEffect(() => {
  console.log("1");
}, []);

컴포넌트가 처음 생성될 때만 함수가 실행


조건부 effect(dependency array)


useEffect의 두 번째 인자는 배열, 조건을 담고 있음, 조건은 어떤 값의 변경이 일어날 때, 배열은 어떤 값의 목록 - 종속성 배열

useEffect(함수, [종속성1, 종속성2, …]) - 처음, state가 변경될 때

useEffect(함수, []) - 처음 한번만 실행

useEffect(함수) - 기본형태 / 컴포넌트가 처음 생성, props나 state가 업데이트될 때


컴포넌트 내 필터링: 전체 목록 데이터를 불러오고, 목록을 검색어로 filter

HTTP 요청의 빈도 감소 / 브라우저(클라이언트) 메모리 부담

컴포넌트 외 필터링: 컴포넌트 외부로 API 요청을 할 때, 필터링(서버에 매번 검색어와 함께 요청하는 경우)

클라이언트 필터링 구현 생각x / 빈번한 HTTP 요청, 서버 부담


로딩 화면(loading indicator) 구현

const [isLoading, setIsLoading] = useState(true);

return {isLoading ? <LoadingIndicator /> : <div>로딩 완료 화면</div>}
useEffect(() => {
  setIsLoading(true);
  fetch(`http://서버주소/proverbs?q=${filter}`)
    .then((resp) => resp.json())
    .then((result) => {
      setProverbs(result);
      setIsLoading(false);
    });
}, [filter]);

댓글남기기