TIL 34일차

안광의·2021년 8월 3일
0

Today I Learned

목록 보기
34/64
post-thumbnail
post-custom-banner

시작하며

오늘은 리액트의 state와 effect를 사용하여 항공 정보를 받아와 출력하고 필터링할 수 있는 페이지를 구현하는 스프린트를 진행하였는데 이전에 배웠던 fetch와 Rest API를 이용하여 데이터를 받아오고 외부에서 필터링하는 코드를 구현하였다.

React

Data Fetching

명언이 담긴 배열을 가져와 리스트를 출력하되, 텍스트 창에 입력한 내용을 포함한 명언들만 필터링해서 출력하는 웹페이지가 있을때 모든 명언들을 받아와 내부에서 필터링하거나 이미 필터링된 데이터만 받아오는 외부에서 필터링하는 방식이 있다.


명언이 담긴 배열을 전달하는 함수

localStorage.setItem(
  "proverbs",
  JSON.stringify([
    "좌절감으로 배움을 늦추지 마라",
    "Stay hungry, Stay foolish",
    "Memento Mori",
    "Carpe diem",
    "배움에는 끝이 없다"
  ])
);
export function getProverbs(filterBy = "") {
  const json = localStorage.getItem("proverbs");
  const proverbs = JSON.parse(json) || [];
  return proverbs.filter((prvb) =>
    prvb.toLowerCase().includes(filterBy.toLowerCase())
  );
}

컴포넌트 내부에서 필터링

import { useEffect, useState } from "react";
import "./styles.css";
import { getProverbs } from "./storageUtil";
export default function App() {
  const [proverbs, setProverbs] = useState([]);
  const [filter, setFilter] = useState("");
  useEffect(() => {
    console.log("언제 effect 함수가 불릴까요?");
    const result = getProverbs();
    setProverbs(result);
  }, []);
  const handleChange = (e) => {
    setFilter(e.target.value);
  };
  return (
    <div className="App">
      필터
      <input type="text" value={filter} onChange={handleChange} />
      <ul>
        {proverbs
          .filter((prvb) => {
            return prvb.toLowerCase().includes(filter.toLowerCase());
          })
          .map((prvb, i) => (
            <Proverb saying={prvb} key={i} />
          ))}
      </ul>
    </div>
  );
}
function Proverb({ saying }) {
  return <li>{saying}</li>;
}

useEffect의 두번째 인자에 빈배열을 넣어 처음에 함수가 생성될 때만 명언 전체의 리스트를 proverbs에 저장한 후, 텍스트에 입력하는 내용을 filter에 저장하여 필터링된 내용이 웹페이지에 출력된다.


컴포넌트 외부에서 필터링

import { useEffect, useState } from "react";
import "./styles.css";
import { getProverbs } from "./storageUtil";
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);
    setProverbs(result);
  }, [filter]);
  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 }) {
  return <li>{saying}</li>;
}

외부에서 필터링 할 경우에는 useEffect의 두번째 인자에 [filter]를 넣어 필터링되는 조건이 바뀔때마다 getProverbs(filter)로 이미 외부에서 필터링된 명언의 목록을 받아와 전체를 출력하게 된다.

장점단점
컴포넌트 내부에서 처리HTTP 요청의 빈도를 줄일 수 있다브라우저(클라이언트)의 메모리 상에 많은 데이터를 갖게 되므로, 클라이언트의 부담이 늘어난다
컴포넌트 외부에서 처리클라이언트가 필터링 구현을 생각하지 않아도 된다빈번한 HTTP 요청이 일어나게 되며, 서버가 필터링을 처리하므로 서버가 부담을 가져간다


로딩 페이지

서버에서 데이터를 받아올때 시간이 오래 걸리는 경우, State를 사용해서 로딩 여부를 표현하고 삼항연산자를 사용하여 렌더링되는 페이지를 전환해주면 로딩 페이지를 구현할 수 있다.

const [isLoading, setIsLoading] = useState(true);
// 생략, LoadingIndicator 컴포넌트는 별도로 구현했음을 가정합니다
return {isLoading ? <LoadingIndicator /> : <div>로딩 완료 화면</div>}
useEffect(() => {
  setIsLoading(true);
  const result = getProverbs(filter);
  setProverbs(result);
  setIsLoading(false);
    });
}, [filter]);

마치며

오랜만에 React를 사용하고 이전에 기초를 배울때 헤맸었기 때문에 어렵지 않을까 했는데, 한번 작동되는 원리를 이해하고 나니 어렵지 않게 챕터를 진행할 수 있었다. 앞으로 더 심화된 내용이 나오기 때문에 복습을 철저히 할 예정이다.

profile
개발자로 성장하기
post-custom-banner

0개의 댓글