React로 필터 컴포넌트 만들기

Andy·2020년 11월 30일
5

개요

학원 팀프로젝트에서 필터를 만들어서 사용했는데 내가 만든 부분이 아니고 이해하기도 힘들뿐아니라 요구사항도 내가 생각하는 것과 달라서 다시 필터 부분을 만들어보고자 하였다.

요구사항

  1. 체크박스를 사용하여 테이블 데이터에 있는 값을 필터한다.
  2. 체크박스 default는 체크가 없는 상태이고 체크 했을 때는 해당 값에 대한 데이터가 테이블에 나와야한다.

  1. 테이블 데이터의 CRUD를 고려하여 체크박스가 자동으로 변경되도록 설계한다.
  2. Material Table 이외에 다른 라이브러리를 사용하지 않는다.
  3. 유저 데이터(json형식), 서버에서 아래와 같은 데이터가 전달 됐다고 가정
      [
        {
          "userId": "kwakky2",
          "name": "곽경열",
          "age": 26,
          "sex": "male"
        },
        {
          "userId": "kwakky3",
          "name": "곽경진",
          "age": 26,
          "sex": "male"
        },
        {
          "userId": "kwakky1",
          "name": "양정욱",
          "age": 26,
          "sex": "male"
        },
        {
          "userId": "kwakky123",
          "name": "김사나",
          "age": 26,
          "sex": "female"
        }

      ]

코드

1. 데이터의 변경에 따라 체크박스도 변경가능 하도록 설계하여 코드를 만들어야한다. 성별은 두 가지 밖에 존재하지 않지만 다른 데이터의 경우 다른 조건들이 발생할 수 있으므로 아래와 같이 코드를 작성한다.

    const getGender = (data) =>{
        const genders = [];
        data.map((person) => {
            if(genders.indexOf(person.sex) === -1) {
                genders.push(person.sex)
            }
        })
        return genders;
    }

indexOf 메서드를 통해서 해당 배열에 map으로 들어오는 데이터가 없을시 데이터를 genders 배열에 넣어서 중복 제거가 된 배열을 만들어 준다.

2. 중복 제거된 데이터를 체크박스 형태로 만들어 준다.

const [checked, setChecked] = useState([])

const renderCheckBoxLists = () => gender.map((value, index)=>
            <div key={index}>
                <span>{value}</span>
                <input
                    type="checkbox"
                    onChange={()=>handleToggle(value)}
                    checked={checked.indexOf(value) !== -1 }
                    value={value}
                />
            </div>
    );

데이터는 어떤게 들어올지 모르는 상태라고 가정했을때 위와 같은 코드로 반복된 코드를 줄일수 있다.
onChange 메소드를 통해 데이터를 전달하고 checked 메소드는 false를 default로 하기 위해서 위와 같이 checked.indexOf(value) !== -1 을 사용했다.

3. 체크 박스의 변동에 따른 배열이 변화하는 function을 만들어준다.

const handleToggle = (value) => {
        const currentIndex = checked.indexOf(value);
        const newChecked = [...checked]

        if(currentIndex === -1) {
            newChecked.push(value)
        } else {
            newChecked.splice(currentIndex, 1)
        }
        setChecked(newChecked)
        props.handleFilters(newChecked)
    }

checked에 들어있는 value의 인덱스 값을 찾아주고 checked에 있는 값들을 newChecked에 담아준다. index값이 없을때는 새로운 값을 넣어주고 아닐경우 그 값을 빼준다.
그리고 newChecked 값을 다시 set해주고 테이블에 해당 값을 전달하기 위해 상위 컴포넌트에서 props로 전달 받은 handleFilters 함수에 결과값을 보내준다.

4. 필터된 값을 상위컴포넌트로 전달한다.

    const [filtering, setFiltering] = useState({
            gender: [],
            age: []
        })
    
    const handleFilters = (filters, category) => {
        const newFilters = {...filtering}
        newFilters[category] = filters
        if(category === "age") {

        }
        if(category === "gender") {
            showFilterResults(newFilters)
            setFiltering(newFilters)
        }
    }
    
    <CheckBox
    handleFilters = {filters => handleFilters(filters, "gender")}
            />
    

일단은 gender 밖에 필터링을 하지 않기 때문에 위와 같이 handleFilters에 "gender"를 스태틱으로 전달하지만 여러가지로 필터링 할 경우에는 해당 데이터에 맞게 하위컴포넌트에서 전달하면 된다.
그리고 카테고리 별로 결과값이 변동되도록 설정해준다.

5. 필터된 값으로 테이블 데이터를 변경한다.

const showFilterResults = (filters) => {
        if(filters.gender.length === 0) {
            setUserList(user)
        } else {
            const filteredResult = Array.from(user).filter((user)=>{
                return filters.gender.indexOf(user.sex) !== -1
            })
            setUserList(filteredResult);
        }
    }

필터 값에 따라 결과값을 만들어 준다. 자바스크립트 배열에서 filter 메소드를 사용하여 해당 필터에 대응하는 결과값을 반환하고 set해준다.

결과

나름대로 원하는 결과값을 만들어냈지만 데이터를 좀 더 다양한 카테고리로 filtering 하는것까지는 포스팅에 담지 못했다. 다음 filter 포스팅에서는 다양한 카테고리로 filtering 되는 컴포넌트를 만들고 위와 같이 리뷰를 할 예정이다.

리액트로 데이터 필터링 하기: https://github.com/kwakky1/filter

profile
Junior Software Developer

0개의 댓글