Effect Hook

Vorhandenheit ·2021년 10월 18일
0

React

목록 보기
10/17

Effect Hook

1. useEffect

  • 리액트 컴포넌트가 렌더링 될 때마다 특정 작업을 실행할 수 있도록하는 hook이다.

1) 기본 형태

useEffect(function, deps)

  • function : 렌더링 이후 실행할 함수
  • deps : 특정한 값이 변경될 때, effect함수를 실행하고 싶을 경우 배열안에 그 값을 넣어줌

A. useEffect(()=> {});
기본형태로 렌더링이 완료될 때마다 실행

B. useEffect(() => {}. []);
useEffect에 설정한 함수가, 화면에 가장 처음 렌더링 될 때만 실행하고 싶을 경우 사용

C. useEffect(() => {document.tile = number }. [number];
첫 렌더링 후 한번 실행, 그 후에는 [] 안의 값이 업데이트 될 때만 실행

D. useEffect(() => { return () => {} })
첫 렌더링 된 후 실행, 그 후에는 렌더링 완료후 뒷정리 함수 반환 후에 실행

2. Side Effect

React 컴포넌트가 렌더링된 이후에 비동기로 처리되어야 하는 부수적인 효과들을 side Effect라고 함
대표적 예로 어떤 데이터르르 가져오기 위해 외부 API를 호출하는 경우, 화면에 렌더링할 수 있는 것은 먼저 렌더링하고 실제 데이터는 비동기로 가져오는 것이 권장

3. 예시

import React, { useState, useEffect } from "react";

function UserListFunction() {
  const [loading, setLoading] = useState(true);
  const [users, setUsers] = useState([]);

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/users")
      .then((response) => response.json())
      .then((users) => {
        setUsers(users); //외부에서 받아온 데이터로 users값이 변하게됨 / side effect 발생
        setLoading(false);
      });
  });

  if (loading) return <div>Loading...</div>;
  return (
    <ul>
      {users.map((user) => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

Hook 규칙

(1) 최상위(at the Top Level)에서만 Hook을 호출해야한다

  • 반복문, 조건문 혹은 중첩된 함수 내에서 hook을 호출하면 안 된다.

왜냐하면, 한 컴포넌트에서 hook을 여러번 호출할 경우, React는 hook 호출의 순서를 기억하고있다. hook 호출의 순서대로 각각의 hook 호출이 무엇인지 식별하는 것입니다.
그렇기 때문에 만약에 조건문 안에 hook이 있을 경우에, 그 조건문이 실행되지 못하면 순서가 뒤바뀌므로, React는 hook을 알맞게 대응할 수가 없습니다.

만약 조건부로 이펙트를 실행하고 싶다면, hook 안에 조건문을 넣어서 이를 해결할 수 있다

(2) 오직 React 함수 내에서 Hook을 호출해야 한다.

-일반적인 JavaScript 함수에서 hook을 호출하면 안된다.

컴포넌트 내에서 필터링

1.컴포넌트 내에서 필터링

전체 목록 데이터를 불러오고, 목록을 검색으로 filter하는 방법

  • HTTP 요청의 빈도를 줄이지만, 브라우저 메모리 상에 많은 데이터를 갖게되어 클라이언트의 부담이 늘어난다.
import { useEffect, useState} from "react";

export default functino App() {
	const [proverbs, setProverbs] = useState([]); // 빈배열
  	const [filter, setFilter] = useState('');
  
  useEffect(() => {
  	const result = getProverbs(); // 속담이 담긴 배열
    setProverbs(result); //속담이 담긴 배열을 받아와서 변수에 집어넣음
  }, []) // 처음 한번만 렌더링
  
  const handleChange = (e) => {
  	setFilter(e.target.value); // input에 입력하면 filter가 입력값으로 바뀜
  }
  
  return (
    <div className="App">
      <input type="text" value={filter} onChange={handleChange} />
      <ul> 
        {proverbs // 받아온 배열에서, input에 입력한 값을 포함하는지 검사
          .filter((prvb) => {
            return prvb.toLowerCase().includes(filter.toLowerCase());
          })
          .map((prvb, i) => (
            <Proverb saying={prvb} key={i} />
          ))}
      </ul>
    </div>
  );
}
function Proverb({ saying }) { // 자식 컴포넌트로, 걸러진 배열을 props로 받음
  return <li>{saying}</li>;
}

2.컴포넌트 외부에서 필터링

컴포넌트 외부로 API 요청을 할 떄, 필터링한 결과를 받아오는 방법

  • 클라이언트가 필터링 구현을 생각하지않아도 되지만, 자주 HTTP 요청을 받아야하며 서버가 필터링을 처리하므로 서버가 부담을 지게된다
import { useEffect, useState } from "react";

export default function App() {
  const [proverbs, setProverbs] = useState([]);
  const [filter, setFilter] = useState("");
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log("언제 effect 함수가 불릴까요?");
    const result = getProverbs(filter); // filter를 여기 집어넣음으로 filter가 바뀔때마다 넘어오는 배열이 달라짐
    setProverbs(result); // 바뀐 배열
  }, [filter]); // filter가 바뀔 때마다 렌더링, 즉 input에 변화가 있을때마다 렌더링 반복

  const handleChange = (e) => {
    setFilter(e.target.value);
  };

  const handleCounterClick = () => {
    setCount(count + 1);
  };

  return (
    <div className="App">
      필터
      <input type="text" value={filter} onChange={handleChange} />
      <ul>
        {proverbs.map((prvb, i) => (
          <Proverb saying={prvb} key={i} />
        ))}
      </ul>
      <button onClick={handleCounterClick}>카운터 값: {count}</button>
    </div>
  );
}

function Proverb({ saying }) { // 자식 컴포넌트 props를 받아옴
  return <li>{saying}</li>;
}

getProverbs를 받아올 때, filter가 추가되어있음

export function getProverbs(filterBy = "") {
  const json = localStorage.getItem("proverbs");
  const proverbs = JSON.parse(json) || [];
  return proverbs.filter((prvb) =>
    prvb.toLowerCase().includes(filterBy.toLowerCase())
  );
}
profile
읽고 기록하고 고민하고 사용하고 개발하자!

0개의 댓글