리액트 3-1. state로 입력에 반응하기 | Reacting to Input with State

드엔트론프·2023년 3월 28일
0

react-study

목록 보기
2/4
post-thumbnail

** 전반적인 내용은 공식문서에 있는 내용입니다.

들어가며

리액트 스터디를 하며, 단순한 (?) 문제를 아주 여러 방면으로 리팩토링 하는 것에 충격을 받았다. 당연하겠지만 어떤 문제건 코드로는 다양하게 나타낼 수 있구나.

아직은 어떤 코드가 베스트다! 하는 건 가려낼 수 없지만, 아 ~ 저 코드 정말 읽기 쉽고 깔끔하다. 는 알 수 있는 듯 하다.

이번 글은 내가 복습하고 문제를 풀다 막혀 다시 풀어본 내용이다.

state로 입력에 반응하기

리액트는 선언적인 방식으로 UI를 조작합니다. 개별적인 UI를 직접 조작하는 것 대신에 컴포넌트 내부에 여러 state를 묘사하고 사용자의 입력에 따라 state를 변경합니다. 이는 디자이너가 UI를 바라보는 방식과 비슷합니다.

리액트는 선언적인 방식을 사용한다. 명령형 방식은 말그대로 하나하나 지시하는 것이라면, 선언적은 선언만 하는것이다.
좀 더 쉽게 말해, 공식문서의 예를 그대로 가져오자면

명령형은 택시에 탄 내가 기사에게 "여기서 왼쪽이요, 그다음 500m 앞에서 오른쪽, 저기서 1차선으로 갈아타시구요" 하는 식이다.

그에 반해 선언형은 내가 택시 기사님께 "00역으로 가주세요" 하는 것이다.

그러면 왜 명령형이 안좋은것일까?
명령형은 단순한 예시에서는 잘 동작하지만, 복잡해질수록 점차 관리하기가 어려워진다고 한다. 그렇기에 리액트는 선언형 프로그래밍을 채택한 것이다.

따라서 리액트의 방식으로 UI를 구현하는건 다음과 같다.

  1. 컴포넌트의 다양한 시각적 상태를 식별합니다.
  2. 상태 변화를 유발하는 요소를 파악합니다.
  3. useState를 사용하여 메모리의 상태를 표현합니다.
  4. 비필수적인 state 변수를 제거합니다.
  5. 이벤트 핸들러를 연결하여 state를 설정합니다.

자세한 내용은 공식문서에서 더 자세히 확인할 수 있다.

Challenge 1 of 3: Add and remove a CSS class

  • 제일 아래에는 다음과 같이 챌린지가 주어진다.
  • 이 문제를 직관적으로 풀지 못했기에 이 글을 쓰는 것이라 봐도 무방하다.

Add and remove a CSS class
코드샌드박스 주소.

문제의 내용은 아래와 같다.

그림을 클릭하면 외부 <div>의 background--active CSS 클래스가 제거되고 <img>에 picture--active 클래스가 추가되도록 하세요. 배경을 다시 클릭하면 원래 CSS 클래스가 복원되어야 합니다.

화면상에서는 그림을 클릭하면 보라색 배경이 제거되고 그림 테두리는 강조 표시됩니다. 그림 바깥쪽을 클릭하면 배경은 강조 표시되고 사진의 테두리 강조 표시는 제거됩니다.

export default function Picture() {
  return (
    <div className="background background--active">
      <img
        className="picture"
        alt="Rainbow houses in Kampung Pelangi, Indonesia"
        src="https://i.imgur.com/5qwVYb1.jpeg"
      />
    </div>
  );
}

처음 주어진 코드는 다음과 같고, css에는 background--activepicture--active가 주어졌다.

어떻게 풀까?

처음에 나는 문제를 보고 useState와 onClick 하나씩 주고 풀면 되겠네~ 하고 풀었다가 실패했다 🫠🫠🫠🫠

둘다 같은 State를 주고 onClick 시 배경을 눌렀으면 background--active를 , 아니면 picture--active를 주려 했는데 그렇게 작성했더니 둘 다 같은 state를 바라봐 문제가 됐던 것.

리액트가 UI 프로그래밍을 어떻게 한다고 했지?

  1. 컴포넌트의 다양한 시각적 상태를 식별합니다.
  2. 상태 변화를 유발하는 요소를 파악합니다.
  3. useState를 사용하여 메모리의 상태를 표현합니다.
  4. 비필수적인 state 변수를 제거합니다.
  5. 이벤트 핸들러를 연결하여 state를 설정합니다.

이렇게 생각해보자.
컴포넌트의 다양한 시각적 상태를 식별합니다.

  • div에는 background--active가 있다. (활성화 되어있다.)
  • img에는 active가 없다. (비활성화 되어있다.

상태 변화를 유발하는 요소를 파악합니다.

  • 뭔가 내가 '클릭' 했을 때 그게 background인지, img인지 파악하면 되겠다.

useState를 사용하여 메모리의 상태를 표현합니다.

  • 이거 active 됐어? 라는 상태를 줘야되겠네
	const [isActive, setIsActive] = useState(false);

이벤트 핸들러를 연결하여 state를 설정합니다.

  • onClcik으로 하나 클릭하면 setIsActive true, 다른 하나는 setIsActive false로 바꿔주면 되겠다.

이렇게 하고나면, 코드는 다음과 같이 작성할 수 있다.

import { useState } from 'react';

export default function Picture() {
  const [isActive, setIsActive] = useState(false);

  let backgroundClassName = 'background';
  let pictureClassName = 'picture';
  if (isActive) {
    pictureClassName += ' picture--active';
  } else {
    backgroundClassName += ' background--active';
  }

  return (
    <div
      className={backgroundClassName}
      onClick={() => setIsActive(false)}
    >
      <img
        onClick={e => {
          e.stopPropagation();
          setIsActive(true);
        }}
        className={pictureClassName}
        alt="Rainbow houses in Kampung Pelangi, Indonesia"
        src="https://i.imgur.com/5qwVYb1.jpeg"
      />
    </div>
  );
}

나는 전반적으로 비슷한 생각의 흐름으로 했는데, 각각의 className을 제대로 주지 않아 실수가 났었다.
참 보고나면 단순한데, 왜 즉각 떠오르지 않는지 😝

쉽다고 생각한 부분도 허투루 넘기지말고 계속 공부해야겠다 !

profile
왜? 를 깊게 고민하고 해결하는 사람이 되고 싶은 개발자

0개의 댓글