본문 바로가기

Libraries/React

[React] Filter (1) 최신순/오래된순 등등 필터링

728x90

 

 

리액트에서 필터 기능을 구현해보자!

 

 


 

 

 만들 예제의 완성본 

 

 

 


 

 

 1. 최신순/오래된순 필터 만들기 

 

 

 1. 컴포넌트를 만든다. 

 

 DiaryList.js 

import { useState } from "react";

const ControlMenu = ({value, onChange, optionList}) => { // (1) 컴포넌트 만들기
  return <select></select>
}


const DiaryList = ({ diaryList }) => {


  return (
    <div>
      <ControlMenu/>  // (2) 컴포넌트 불러오기
      {diaryList.map((it) => (
        <div key={it.id}>{it.content}</div>
      ))}
    </div>
  );
};

DiaryList.defaultProps = {
  diaryList: [],
};

export default DiaryList;

 

// (1) ControlMenu 컴포넌트를 만든다. (ControlMenu의 역할은 sortType (정렬기준)을 변화시키는 select역할)

// (2) return 구문 안에 컴포넌트를 불러온다.

 

value: select가 어떤 것을 선택하고 있는지 (필터의 값)

onChange: select가 선택하는게 변화했을 때 바꿀 기능 (필터를 바꾸는 함수)

optionList: select 태그 안에 들어갈 옵션 

 

 

 

 2. state를 생성하고, 선택항목을 생성한다. 

 

import { useState } from "react";

const sortOptionList = [   // (6) 선택 항목 생성
  { value: "latest", name: "최신순" },
  { value: "oldest", name: "오래된 순" },
];

const ControlMenu = ({ value, onChange, optionList }) => {
  return (
    // (8) select에 전달
    <select value={value} onChange={(e) => onChange(e.target.value)}> 

    </select>
  );
};

const DiaryList = ({ diaryList }) => {
  const [sortType, setSortType] = useState("latest"); // (3) sortType state 샌성

  return (
    <div>
      <ControlMenu
        value={sortType} // (4) state 전달
        onChange={setSortType} // (5) setState 전달
        optionList={sortOptionList} // (7) sortOptionList 전달
      />
      {diaryList.map((it) => (
        <div key={it.id}>{it.content}</div>
      ))}
    </div>
  );
};

DiaryList.defaultProps = {
  diaryList: [],
};

export default DiaryList;

 

 

// (3) sortType state 생성, 초기값은 최신순

// (4),(5),(7) ControlMenu 컴포넌트에 props 전달

// (6) sortOptionList에 선택항목 생성

 

 

 

 3. 옵션을 구현한다. 

 

import { useState } from "react";

const sortOptionList = [
  { value: "latest", name: "최신순" },
  { value: "oldest", name: "오래된 순" },
];

const ControlMenu = ({ value, onChange, optionList }) => {
  return (
    <select value={value} onChange={(e) => onChange(e.target.value)}>
      {/* (9) 옵션 구현 */}
      {optionList.map((it, idx) => (
        <option key={idx} value={it.value}>
          {it.name}
        </option>
      ))}
    </select>
  );
};

const DiaryList = ({ diaryList }) => {
  const [sortType, setSortType] = useState("latest");

  return (
    <div>
      <ControlMenu
        value={sortType}
        onChange={setSortType}
        optionList={sortOptionList}
      />
      {diaryList.map((it) => (
        <div key={it.id}>{it.content}</div>
      ))}
    </div>
  );
};

DiaryList.defaultProps = {
  diaryList: [],
};

export default DiaryList;

 

// (9) 옵션 구현

onChange이벤트가 일어나게되면 이벤트객체의 target의 value를 전달해서 ▶ onChange(e.target.value)

prop으로 받은 onChange메서드를 실행을 시키는데, 이거는 setSortType이었기 때문에 onChange={setSortType}

sortType을 최신순으로 선택하면 latest가 되고, 오래된 순으로 선택하면 oldest로 된다. 

 

 

 

 4. 필터에 따라서 리스트가 보여지는게 달라지게하기 

 

import { useState } from "react";

const sortOptionList = [
  { value: "latest", name: "최신순" },
  { value: "oldest", name: "오래된 순" },
];

const ControlMenu = ({ value, onChange, optionList }) => {
  return (
    <select value={value} onChange={(e) => onChange(e.target.value)}>
      {optionList.map((it, idx) => (
        <option key={idx} value={it.value}>
          {it.name}
        </option>
      ))}
    </select>
  );
};

const DiaryList = ({ diaryList }) => {
  const [sortType, setSortType] = useState("latest");

  // (10) 필터에 따라 리스트 정렬 (최신순인지 오래된순인지 if문으로 분기를 달아서 정렬된 리스트를 반환하는 함수)
  const getProcessedDiaryList = () => { 

  const compare = (a,b)=> { // 비교해주는 함수
    if(sortType ==='latest'){
      return parseInt(b.date) - parseInt(a.date); // 문자열이 들어올수도 있어서 parseInt로 숫자로 바꿔줌
    }else{
      return parseInt(a.date) - parseInt(BeforeUnloadEvent.date);
    }
  }
  const copyList = JSON.parse(JSON.stringify(diaryList));
  const sortedList = copyList.sort(compare);
  return sortedList;
  }

  return (
    <div>
      <ControlMenu
        value={sortType}
        onChange={setSortType}
        optionList={sortOptionList}
      />
      {getProcessedDiaryList().map((it) => ( // (11) 함수 적용
        <div key={it.id}>{it.content}</div>
      ))}
    </div>
  );
};

DiaryList.defaultProps = {
  diaryList: [],
};

export default DiaryList;

 

// (10) 필터에 따라 리스트 정렬  (최신순인지 오래된순인지 if문으로 분기를 달아서 정렬된 리스트를 반환하는 함수)

배열에 sort를 쓰면 원본 배열자체가 재정렬이 돼버리기때문에

깊은 복사를 해서 데이터를 붙여넣어줘야한다.

▶ const copyList = JSON.parse(JSON.stringify(diaryList));

diaryList가 배열인데, 배열을 JSON화를 해서 문자열로 바꿔버린다.

문자열로 반환된거를 JSON.parse를 실행시키면 다시 배열로 복구가 된다.

이거를 copyList로 넣어주는 것이다.

결국 정리하자면,  diaryList에 있는 원본 배열의 값이 문자열로 바꼈다가 배열로 바뀌게 되는 것이다.

원본 배열을 안건드리고 복사가 돼서 copyList에 넣어진다.

 

 

 최신순/오래된순 필터 완성본 

 

 

 


 

 

 2. 감정 필터 만들기 (전부다/좋은감정만/안좋은감정만) 

 

 

 1. filter state와 선택항목 생성하고 컴포넌트에 props 전달하기 

 

import { useState } from "react";

const sortOptionList = [
  { value: "latest", name: "최신순" },
  { value: "oldest", name: "오래된 순" },
];

const filterOptionList = [ // (2) 선택항목 생성
  { value: "all", name: "전부 다" },
  { value: "good", name: "좋은 감정만" },
  { value: "bad", name: "안좋은 감정만" },
];

const ControlMenu = ({ value, onChange, optionList }) => {
  return (
    <select value={value} onChange={(e) => onChange(e.target.value)}>
      {optionList.map((it, idx) => (
        <option key={idx} value={it.value}>
          {it.name}
        </option>
      ))}
    </select>
  );
};

const DiaryList = ({ diaryList }) => {
  const [sortType, setSortType] = useState("latest");
  const [filter, setFilter] = useState("all"); // (1) filter state 생성

  const getProcessedDiaryList = () => {
    const compare = (a, b) => {
      if (sortType === "latest") {
        return parseInt(b.date) - parseInt(a.date);
      } else {
        return parseInt(a.date) - parseInt(BeforeUnloadEvent.date);
      }
    };
    const copyList = JSON.parse(JSON.stringify(diaryList));
    const sortedList = copyList.sort(compare);
    return sortedList;
  };

  return (
    <div>
      <ControlMenu
        value={sortType}
        onChange={setSortType}
        optionList={sortOptionList}
      />
      <ControlMenu  // (3) 컴포넌트 불러와서 props 전달하기
        value={filter}
        onChange={setFilter}
        optionList={filterOptionList}
      />
      {getProcessedDiaryList().map((it) => (
        <div key={it.id}>{it.content}</div>
      ))}
    </div>
  );
};

DiaryList.defaultProps = {
  diaryList: [],
};

export default DiaryList;

 

// (1) filter state 생성 (초기값은 전부다(all))
// (2) 선택항목 생성 (전부다 / 좋은감정만 / 안좋은감정만)
// (3) ControlMenu 컴포넌트 불러와서 props 전달하기

 

 

 

 2. copyList를 필터링하기 

 

import { useState } from "react";

const sortOptionList = [
  { value: "latest", name: "최신순" },
  { value: "oldest", name: "오래된 순" },
];

const filterOptionList = [
  { value: "all", name: "전부 다" },
  { value: "good", name: "좋은 감정만" },
  { value: "bad", name: "안좋은 감정만" },
];

const ControlMenu = ({ value, onChange, optionList }) => {
  return (
    <select value={value} onChange={(e) => onChange(e.target.value)}>
      {optionList.map((it, idx) => (
        <option key={idx} value={it.value}>
          {it.name}
        </option>
      ))}
    </select>
  );
};

const DiaryList = ({ diaryList }) => {
  const [sortType, setSortType] = useState("latest");
  const [filter, setFilter] = useState("all");

  const getProcessedDiaryList = () => {

    const filterCallBack = (item) => {   // (5) 3이하는 좋은감정, 3초과는 안좋은감정으로 필터링되게하기
      if (filter === "good") {
        return parseInt(item.emotion) <= 3;
      } else {
        return parseInt(item.emotion) > 3;
      }
    };

    const compare = (a, b) => {
      if (sortType === "latest") {
        return parseInt(b.date) - parseInt(a.date);
      } else {
        return parseInt(a.date) - parseInt(BeforeUnloadEvent.date);
      }
    };
    const copyList = JSON.parse(JSON.stringify(diaryList));

    const filteredList = filter === "all" ? copyList : copyList.filter((it)=>filterCallBack(it)); // (4) copyList를 필터링 하기

    const sortedList = filteredList.sort(compare); // (6) filteredList 적용하기
    return sortedList;
  };

  return (
    <div>
      <ControlMenu
        value={sortType}
        onChange={setSortType}
        optionList={sortOptionList}
      />
      <ControlMenu
        value={filter}
        onChange={setFilter}
        optionList={filterOptionList}
      />
      {getProcessedDiaryList().map((it) => (
        <div key={it.id}>
          {it.content}
          {it.emotion}
        </div>
      ))}
    </div>
  );
};

DiaryList.defaultProps = {
  diaryList: [],
};

export default DiaryList;

 

// (4) copyList를 필터링 하기
// (5) 3이하는 좋은감정, 3초과는 안좋은감정으로 필터링되게하기 ( getProcessedDiaryList가 정렬 조건에 따라서 정렬해서 반환했던 리스트를 필터링을 거쳐서 정렬하도록 만들어줘야함)
// (6) filteredList 적용하기

 

 

 전체 완성본 

 

 

두 필터 다 정상 작동된다.

 

 

 

 

"검색 필터" 만드는 방법이 궁금하시다면, 아래의 게시글을 참고하세요!


https://dev-ini.tistory.com/108

 

[React] 검색창, 검색어, 검색 필터 (filter) 기능 구현 (검색창 만들기)

검색 필터 기능을 구현해보자! 만들 예제의 완성본 1. 가게 이름을 검색하면 해당 검색어와 일치하는 가게가 필터 돼서 뜬다. 2. 해당하는 가게가 없을 경우 "검색 결과가 없습니다."가 뜬다. 구현

dev-ini.tistory.com

 

728x90