개발 알다가도 모르겠네요

프로그래밍 언어 검색 -3 본문

웹/프론트엔드 직군 과제

프로그래밍 언어 검색 -3

이재빵 2022. 8. 27. 08:41
728x90

App의 state에 선택한 언어 추가

App 컴포넌트의 Suggestion 컴포넌트 생성하는 쪽에 선언해둔 onSelect 코드에 selectedLanguages를 자신의 state에 추가해보자.

 

//App.js
import { fetchLanguages } from "./api.js";
import SearchInput from "./SearchInput.js";
import Suggestion from "./Suggestion.js";

export default function App({ $target }) {
  this.state = {
    fetchedLanguages: [],
    selectedLanguages: [],
  };

  this.setState = (nextState) => {
    this.state = {
      ...this.state,
      ...nextState,
    };
    suggestion.setState({
      selectedIndex: 0,
      items: this.state.fetchedLanguages,
    });
  };

  const searchInput = new SearchInput({
    $target,
    initialState: "",
    onChange: async (keyword) => {
      if (keyword.length === 0) {
        this.setState({
          fetchedLanguages: [],
        });
      } else {
        const languages = await fetchLanguages(keyword);
        this.setState({
          fetchedLanguages: languages,
        });
      }
    },
  });

  const suggestion = new Suggestion({
    $target,
    initialState: {
      cursor: 0,
      items: [],
    },
    onSelect: (language) => {
      alert(language);

	  //추가된 부분
      //이미 선택된 언어인 겨우, 맨 뒤로 보내버리는 처리
      const nextSelectedLangunages = [...this.state.selectedLanguages];

      const index = nextSelectedLangunages.findIndex(
        (selectedLanguage) => selectedLanguage === language
      );

      if (index > -1) {
        //해당 언어의 index를 잘라서 제일 뒤에 푸시한다.
        nextSelectedLangunages.splice(index, 1);
      }
      nextSelectedLangunages.push(language);

      this.setState({
        ...this.state,
        selectedLanguages: nextSelectedLangunages,
      });
    },
  });
}

 

 

 

SelectedLanguages 구현

작업하기에 앞서, index.html 내용 중 <div class="SelectedLanguage"></div> 코드를 제거한다.

해당 마크업은 SelectedLanguages 컴포넌트에 넣어준다.

 

//index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>2022 FE 데브매칭</title>
    <link rel="stylesheet" href="./style.css" />
  </head>
  <body>
    <main class="App"></main>
    <script defer src="./index.js" type="module"></script>
  </body>
</html>

 

//SelectedLanguages.js
export default function selectedLanguage({ $target, initialState }) {
  this.$element = document.createElement("div");
  this.$element.className = "SelectedLanguage";
  this.state = initialState;

  $target.appendChild(this.$element);

  this.setState = (nextState) => {
    this.state = nextState;
    this.render();
  };

  this.render = () => {
    this.$element.innerHTML = `<ul> ${this.state
      .map((item) => `<li>${item}</li>`)
      .join("")}</ul>`;
  };
  this.render();
}

 

이후 App 컴포넌트에서 SelectedLanguages 컴포넌트를 생성하고, App 컴포넌트의 setState 함수 내에서 

SelectedLanguages의 setState를 호출, 상태를 변경하도록 한다.

 

//App.js
import { fetchLanguages } from "./api.js";
import SearchInput from "./SearchInput.js";
import SelectedLanguage from "./SelectedLanguages.js";
import Suggestion from "./Suggestion.js";

export default function App({ $target }) {
  this.state = {
    fetchedLanguages: [],
    selectedLanguages: [],
  };

  this.setState = (nextState) => {
    this.state = {
      ...this.state,
      ...nextState,
    };
    suggestion.setState({
      selectedIndex: 0,
      items: this.state.fetchedLanguages,
    });
    
    //추가된 부분
    selectedLanguages.setState(this.state.selectedLanguages);
  };

  const selectedLanguages = new SelectedLanguage({
    $target,
    initialState: [],
  });


//코드 생략   
}

 

 

실행 결과

 

 

 

5개까지만 선택할 수 있게 수정

SelectedLanguages에서 state로 받은 selectedLanguages 배열의 값이 5개를 초과하면 앞부분을 잘라 버리도록 처리해보자.

 

//SelectedLanguages.js
//최대값 추가
const MAX_DISPLAY_COUNT = 5;
export default function SelectedLanguage({ $target, initialState }) {
  this.$element = document.createElement("div");
  this.$element.className = "SelectedLanguage";
  this.state = initialState;

  $target.appendChild(this.$element);

  this.setState = (nextState) => {
    this.state = nextState;

//추가된 부분
    if (this.state.length > MAX_DISPLAY_COUNT) {
      const startPosition = this.state.length - MAX_DISPLAY_COUNT;
      this.state = this.state.slice(
        startPosition,
        MAX_DISPLAY_COUNT + startPosition
      );
    }

    this.render();
  };

  this.render = () => {
    this.$element.innerHTML = `<ul> ${this.state
      .map((item) => `<li>${item}</li>`)
      .join("")}</ul>`;
  };
  this.render();
}

 

 

완성 화면

' > 프론트엔드 직군 과제' 카테고리의 다른 글

프로그래밍 언어 검색 -2  (0) 2022.08.26
프로그래밍 언어 검색 -1  (0) 2022.08.26