ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • React_기초 정리 1편 (useState, modal, sort 메소드, like 구현)
    도쿄/개발 2023. 10. 20. 18:27

    안녕하세요. youngKoala입니다.

    오늘부터 React와 Typescript를 사용해서 다음과 같은 기능을 가진 페이지를 만들어보려고 합니다.

    • 👍 아이콘을 누르는 횟수만큼 숫자가 증가한다.
    • 제목을 누르면 모달창이 생겨나고, x표시로 모달창을 닫는다.
    • input창에 내용을 입력하고 "저장" 버튼을 누르면 리스트에 업데이트 된다.
    • "도쿄 → 싱가포르" 버튼을 누르면 "도쿄"가 "싱가포르"로 바뀐다.
    • "오름차순" 버튼을 누르면, 리스트가 가나다순, abc, 123과 같은 오름차순으로 정렬이 이루어진다.
    • "오름차순" 버튼을 누르면, 내림차순 정렬(역정렬)이 이루어진다.

     

    1. 우선 JSX return 부분부터 짜봅시다.

    (CSS스타일을 위한 className은 어지러우니 여기서는 생략하겠습니다.)

    //App.js return 부분
    return (
        <div>
          <div>
            <h4>React Blog</h4>
          </div>
          <button onClick={changeCapitalChange}> 도쿄 → 싱가포르 </button>
          <button onClick={makeListSort}> 오름차순 </button>
          <button className="button" onClick={makeListReverse}> 내림차순 </button>
          {list.map((el:any, idx:number) => 
            (
              <div key={idx}>
              <h4 onClick={() => openModal()}>
              {el.title}
                <span onClick={(e) => {
                e.stopPropagation(); 
                updateLike(idx)}}>  
                👍
                </span> 
                {el.like}
              </h4>
            </div>    
            )
          )}
          <input type='text' onChange={(e) => textHandler(e)}/>
          <button onClick={saveToList}> 저장 </button>
        {popModal ? <Modal list={list} num={number} setPopModal={setPopModal}/> : null}
        </div>
      );

     

     

    1. 서버로부터 데이터를 받아왔다고 가정하고, 우선 list 배열에 초기값을 생성합니다. 

     //list의 type정의
      type listType = {
    	title: string;
    	like: number;
      };
    
      //리스트에 text, like로 구성된 오브젝트 배열 초기 생성
      const [list, setList] = useState<listType[]>([
        { text: '도쿄', like: 0 }, //list[0]
        { text: '서울', like: 0 }, //list[1]
        { text: '웰링턴', like: 0 }, //list[2]
        { text: '런던', like: 0 }, //list[3]
      ])

     

    2. 기능 구현에 필요한 값을 저장할 수 있는 useState를 생성해 봅시다.

    //modal창을 true, false로 열고 닫기 위한 useState
    const [popModal, setPopModal] = useState<boolean>(false);
      
    //클릭된 리스트의 인덱스값을 저장하는 useState
    const [index, setIndex] = useState<number>(0);
      
    //input창에 입력된 내용을 저장하는 useState
    const [inputContent, setInputContent] = useState<string>('');

     

    3. 마지막으로 각 기능을 구현한 함수를 생성합니다.

    //👍 아이콘을 누르면 해당 리스트의 like값을 증가시키는 함수
      const updateLike = (idx:number):void => {
        const newList:listType[] = [...list];
        newList[idx].like += 1;
        setList(newList);
      }
      
      // 버튼을 눌렀을 때 "도쿄"를 "싱가포르"로 변경시켜보는 함수
      const changeCapitalChange = ():void => {
        const newList:listType[] = [...list];
        newList.map((el,idx) => {
          if(el.title === "도쿄") el.title = "싱가포르";
          setList(newList);
        })
        //map을 더욱 간단하게 바꿔보자면
        //setList(list.map(el => (el.title === "도쿄" ? { ...el, title: "싱가포르" } : el)));
      }
      
      //list를 오름차순으로 정렬하는 함수
      const makeListSort = ():void => {
        const newList:listType[] = [...list];
        //newList.sort(); 와 같다
        newList.sort((a,b) => a.title > b.title ? 1 : ((b.title > a.title) ? -1 :0));
        setList(newList);
      }
      
      //list를 내림차순으로 정렬하는 함수
      const makeListReverse = ():void => {
        const newList:listType[] = [...list];
        //newList.reverse(); 와 같다
        newList.sort((a,b) => a.title < b.title ? 1 : ((b.title < a.title) ? -1 :0));
        setList(newList);
      }
    
      //modal창을 보이게 하는 함수
      //default는 false로 지정해놓고, popModal값이 true일 경우 Modal컴포넌트를 실행한다.
      const openModal = (idx:number):void => {
        setNumber(index);
        setPopModal(true);
      }
      
      //입력 내용을 setInputContent에 저장시키는 함수
      const textHandler = (e:React.MouseEvent<HTMLDivElement>):void => {
        setInputContent(e.target.value);
      }
      
      //새로운 내용을 list state에 추가하는 함수
      const saveToList = ():void => {
        const newList:listType[] = [...list];
        //push 메소드를 통해newList에 새로운 오브젝트 추가
        newList.push({title:inputContent, like: 0})
        setIndex(newList);
        //input창 초기화
        setInputContent('');
      }

     

    4. 마지막으로 중요한 부분을 짚고 넘어갈게요.

    1) 우선 반복적으로 보이는 이 구조는 list의 복사본을 생성하는 코드인데요.

    const newList:listType[] = [...list];
    //code
    setList(newList);

     

    state에 저장된 데이터타입이 배열(array)나 오브젝트(object)인 경우,

    복사본을 만들고 그 복사본에서 값 변경 및 수정을 통해 set해 주어야 합니다.

    왜냐하면 기존 state의 값과  신규 state의 값이 같다면(==),  값 변경은 일어나지 않아요. 

    이는 데이터의  불변성을 지키기 위해서인데요, 

    불변성이 지켜지지 않으면 내부의 값이 변경되어도 값이 바뀐것을 감지하지 못합니다.

    따라서 spread operator(...)로 기존의 state값은 유지시키고, 그것의 복사본 내부의 값을 바꿔주어야

    기존 state의 값과  신규 state의 값이 같지 않다는 (!==) 것을 인식하고 변경된 값을 set해 주는 원리입니다.

     

     

    2) list의 인덱스(idx)를 통해 openModal 함수와 updateLike함수를 구현하는 부분

    {list.map((el:any, idx:number) =>

    onClick이벤트를 걸어 클릭된 리스트의 인덱스값이 함수로 전달합니다.

    updateLike함수의 경우는 바로 해당 인덱스값을 가진 오브젝트의 like 수를 증가시키고 있고요.

    newList[idx].like += 1;

    openModal 함수의 경우는 modal창을 여는 데에 인덱스값이 사용되고 있지는 않지만,

    인덱스값을 setNumber에 set해서 modal창에 해당 인덱스 값을 가진 오브젝트의 title을 표시할 수 있도록 하고 있습니다.

    {list[number].title}

     

    3) makeListSort함수의 sort 메소드 & makeListReverse함수의 reverse 메소드

    //오름차순 정렬
    newList.sort((a,b) => a.title > b.title ? 1 : ((b.title > a.title) ? -1 :0));
    newList.sort();
    
    //내림차순 정렬
    newList.sort((a,b) => a.text < b.text ? 1 : ((b.text < a.text) ? -1 :0));
    newList.reverse();

    아주 간단히 설명하면 sort메소드와 reverse메소드는 인접한 요소의 비교를 통해 지정 위치(인덱스)를 바꿔나가는 원리예요.

    정렬 파트는 분량이 방대해서 곧 정렬 알고리즘에 대한 포스팅을 할 때 더 자세히 설명해드리도록 할게요.

    각 정렬 방식에 따라서 내부가 어떻게 구현되고 있는지를 알아야 할 필요성이 있는 중요한 개념이에요!

    우선은 Mozilla에서 설명하는 sort메소드 부분의 링크를 걸어둘게요.

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

     

    Array.prototype.sort() - JavaScript | MDN

    The sort() method of Array instances sorts the elements of an array in place and returns the reference to the same array, now sorted. The default sort order is ascending, built upon converting the elements into strings, then comparing their sequences of UT

    developer.mozilla.org

     

    내용이 길어지는 것 같아 modal에 관한 내용은 2편에서 다루도록 하겠습니다.

    반응형