#22.TIL | React(sort를 활용하여 분류하기)

Seongjae Hwang·2021년 11월 28일
0


😈👿 ← 귀여운 몬스터 🔝 안귀여운 몬스터

select태그에서 이벤트 받기

function Monsters() {
  const [monsters, setMonsters] = useState([]);

  const [search, setSearch] = useState("");
  const [callbackSearch, setcallbackSearch] = useState("");

  const [sort, setSort] = useState();

  useEffect(() => {
    fetch(`https://jsonplaceholder.typicode.com/users`)
      .then((response) => response.json())
      .then((json) => setMonsters(json));
  }, []);

  return (
    <div className="monsters">
      <input
        value={search}
        placeholder="몬스터찾기"
        type="text"
        onChange={(e) => {
          setSearch(e.target.value);
        }}
      />

      <button
        onClick={() => {
          setcallbackSearch(search);
        }}
      >
        검색
      </button>

      <button
        onClick={() => {
          setSearch("");
        }}
      >
        검색창 초기화
      </button>

      <button
        onClick={() => {
          setcallbackSearch("");
          setSearch("");
        }}
      >
        홈버튼
      </button>

      <select
        onChange={(e) => {
          setSort(e.target.value);
        }}>
        <option value="">--정렬하기--</option>
        <option value="short">이름 짧은 순</option>
        <option value="long">이름 긴 순</option>
      </select>

      <CardList monsters={monsters} search={callbackSearch} sort={sort} />
    </div>
  );
}

먼저, 목록들을 정렬하기 위해 select태그를 사용하여 각각의 태그의 value를 알아낼려고 했었는데 select태그에서는 onClick이벤트 사용이 불가능 하였고, onChange이벤트를 사용해 선택한 value가 무엇인지 알 수 있었다.
따라서, 알아낸 value를 sort라는 state에 넣고, 이를 CardList.js에게 props로 전달하였다.

props.sort값에 따른 조건부 랜더링

function CardList(props) {
return (
    <div className="cardList">
  
    {props.sort === "short" &&
        props.monsters
          .sort(function (a, b) {
            if (a.name.length > b.name.length) {
              return 1;
            }
            if (a.name.length < b.name.length) {
              return -1;
            }
            return 0;
          })
          .filter((monster) => monster.name.includes(props.search))
          .map((monster) => (
            <Card id={monster.id} name={monster.name} email={monster.email} />
          ))}
          
      {props.sort === "long" &&
        props.monsters
          .sort(function (a, b) {
            if (a.name.length > b.name.length) {
              return -1;
            }
            if (a.name.length < b.name.length) {
              return 1;
            }
            return 0;
          })
          .filter((monster) => monster.name.includes(props.search))
          .map((monster) => (
            <Card id={monster.id} name={monster.name} email={monster.email} />
          ))}
          
      {props.sort === undefined &&
        props.monsters
          .filter((monster) => monster.name.includes(props.search))
          .map((monster) => (
            <Card id={monster.id} name={monster.name} email={monster.email} />
          ))}
          
    </div>
  );
}

가독성 제로에다가 하드코딩했지만,,, 내가 의도했던 바는 select에서 선택한 값의 value를 props로 전달하고, 이를 활용하여 각각 다른 랜더링을 보여주는 것이었다.

그래서

1. props.sort의 값이 "short"일때는 a.name.length 즉, 객체의 value값들을 비교하여 새로운 순서의 배열을 반환하고,

2, 이를 filter를 사용하여 props.search의 값을 포함하는 새로운 배열을 반환하고, (예를 들어 props.serach의 값이 "C"라면 다음과 같은 배열)

3. 이 새로운 배열의 index 개수를 가지고 map을 사용하여 여러개의 Card.js 컴포넌트를 찍어내게 한다.

아쉬운점

  • filter로 모든 데이터를 순회
  • value가 여러개면 각각의 조건에 맞는 컴포넌트들을 하드코딩해야 하는지
  • 변수사용
profile
Always Awake

0개의 댓글