react 검색 구현 (filter 활용)

하고 싶었던 것

  • 몬스터 목록을 fetch로 조회하여 state에 저장한 후,
  • 검색어를 입력 시 이름이 일치하는 몬스터만 보이도록 구현하려고 합니다.

✏️ Monsters.js

class Monsters extends Component {
  state = {
    monsters: [],
    userInput: "",
  };

  // 데이터 로딩
  componentDidMount() {
    fetch("https://jsonplaceholder.typicode.com/users")
      .then((res) => res.json())
      .then((data) => {
        this.setState({ monsters: data });
      });
  }
  
  render() {
    return (
      <div className="Monsters">
        <h1>컴포넌트 재사용 연습!</h1>
        <SearchBox handleChange={this.handleChange} />
        <CardList />
      </div>
    );
  }
}

내가 한 것

handleChange = (e) => {
  this.setState({
    searchKeyword: e.target.value,
    monsters: this.state.monsters.filter(
      monster => monster.name.includes(e.target.value)
    })
  });
}
...

        <SearchBox handleChange={this.handleChange} />
        <CardList monsters={this.state.monsters} />

검색어가 입력될 때 state.monster를 업데이트 하였는데, 원본 데이터가 훼손되는 문제가 발생하였습니다.
검색어를 입력할 때마다 몬스터 state도 변경되어 버렸습니다.

문제해결까지 가는 길

  • 원본 데이터를 저장해두는 state를 추가할 것인지
  • 검색어를 입력할 때 마다 fetch하여 데이터를 조회해 올 것인지 고민하였는데
    모두 비효율적인 것 같아 고민하던 중 모법답안을 발견하였습니다.😅

모법 답안!

  • 몬스터 목록을 하위 컴포넌트로 넘겨줄 때, state 원본이 아닌 filter된 몬스터의 목록을 보내주는 것입니다.
  render() {
    const filteredMonsters = this.state.monsters.filter((monster) =>
      monster.name.includes(this.state.userInput)
    );
    return (
      <div className="Monsters">
        <h1>컴포넌트 재사용 연습!</h1>
        <SearchBox handleChange={this.handleChange} />
        <CardList monsters={filteredMonsters} />
      </div>
    );
  }

리액트의 컴포넌트 나누는 것의 이점도 잘 느낄 수 있었습니다.

검색과 필터 기능을 구현할 때 매번 서버와 통신할 필요 없이 빠르게 구현이 가능하니, 좋은 개발 노하우인 것 같습니다.

좋은 웹페이지 즐겨찾기