Props, State, Lifecycle

jytrack·2022년 5월 19일
0
post-thumbnail

목차


1. Props

  • Props 사용법
  • Props 기본값 설정
  • props.children

2. State

3. Lifecycle


props


공식문서 - Components and Props

  • 컴포넌트에 직접 주입하는 값을 props라고 한다.

    • childrenprops의 일부이다.
    • propsclassName이나 여러 handler를 줄 수도 있다.
    • 읽기 전용이므로 입력값을 바꾸려 하지 않고 읽어와서 사용해야 한다. (순수 함수)

  • 컴포넌트 합성

    • 여러 개를 하나의 컴포넌트에 넣는 것이다.
    • 컴포넌트 안에서 새로운 컴포넌트를 넣어서 구성할 수 있다.
    function App() {
      return (
        <div>
          <Welcome name="Sara" />
          <Welcome name="Cahal" />
          <Welcome name="Edite" />
        </div>
      );
    }
  • 컴포넌트 추출

    • 유의미한 값들로 추출해서 새로운 컴포넌트를 만드는 것이다.
    • 재사용성을 높이기 위한 방법 중 하나이다.
    • 여러 번 사용되는 UI(Button, Avatar 등)나 복잡한 구조의 UI를 컴포넌트로 추출하는 것이 좋다.

1. props 기본 사용법


App 컴포넌트에서 Fruit 컴포넌트를 사용할 때, 'name' 값을 전달해주고 싶다면 다음처럼 하면 된다.

const App = () => {
  return (
    <Fruit name="Apple" />
  )
}

그리고 전달한 값을 Fruit 컴포넌트에서 사용하려면 Fruit 컴포넌트 인자로 props를 전달해주고, props.name으로 접근해서 name 값을 사용할 수 있다.
이때, props는 객체 형태로 전달된다!

const Fruit = (props) => {
  return (
    <>
    <div>{props.name}</div>
    </>
  )
}

👉 실행결과

2. 여러 개의 props


Fruit 컴포넌트에 다른 props(color, emoji)도 전달해보았다.
Fruit 컴포넌트에서 이를 받아와서 props.color로 배경색을 지정하고, props.name 아래에 props.emoji도 출력해보았다.

const Fruit = (props) => {
  return (
    <>
      <div style={{backgroundColor: props.color}}>{props.name}</div>
      <div>{props.emoji}</div>
    </>
  )
}

const App = () => {
  return (
    <>
      <Fruit name="Apple" color="Red" emoji="🍎" />
      <br/>
      <Fruit name="Banana" color="Yellow" emoji="🍌" />
    </>
  )
}

👉 실행결과

🤔 비구조화 할당
매번 접근할 때마다 props.~~~을 입력하는 게 번거롭다면, Fruit의 인자에 비구조화 할당을 사용하여 좀 더 간결하게 작성할 수도 있다.

const Fruit = ({name, color, emoji}) => {
  return (
    <>
      <div style={{backgroundColor: color}}>{name}</div>
      <div>{emoji}</div>
    </>
  )
}

3. defaultProps


컴포넌트에 props 값을 지정하지 않았을 때, 기본값을 설정할 수 있다.
name, color, emoji의 기본값으로 모두 ???을 주었다.

const Fruit = (props) => {
  return (
    <>
      <div style={{backgroundColor: props.color}}>{props.name}</div>
      <div>{props.emoji}</div>
    </>
  )
}

Fruit.defaultProps = {
  name: "???",
  color: "???",
  emoji: "???"
}

const App = () => {
  return (
    <>
      <Fruit name="Apple" color="Red" emoji="🍎" />
      <br />
      <Fruit name="Banana" color="Yellow" emoji="🍌" />
      <br />
      <Fruit />
      <br />
      <Fruit color="Purple" emoji="🍇" />
    </>
  )
}

👉 실행결과
props를 아무것도 전달하지 않은 <Fruit /> 는 name, emoji 부분에 모두 '???'이 출력되고 배경색이 바뀌지 않은 것을 알 수 있다. 또한, name을 전달하지 않은 <Fruit color="Purple" emoji="🍇" />는 name 부분에 '???'이 출력된 것을 알 수 있다.

4. props.children


Fruit 컴포넌트를 감싸는 Wrapper 컴포넌트를 새로 만들었다.

const Wrapper = () => {
  return (
    <div style={{border: "3px solid black", width: 400, height: 300}}></div>
  )
}

const App = () => {
  return (
    <>
      <Wrapper>
        <Fruit name="Apple" color="Red" emoji="🍎" />
        <br />
        <Fruit name="Banana" color="Yellow" emoji="🍌" />
        <br />
        <Fruit />
        <br />
        <Fruit color="Purple" emoji="🍇" />
      </Wrapper>
    </>
  )
}

👉 실행결과
실행해보면 Fruit 컴포넌트들이 화면에 출력되지 않았다.

❗ 이때, Wrapper 컴포넌트에 props를 전달하여 props.children을 렌더링 해주어야 한다.

const Wrapper = (props) => {
  return (
    <div style={{border: "3px solid black", width: 400, height: 300}}>
      {props.children}
    </div>
  )
}

👉 실행결과
Wrapper 태그 내부에 있던 Fruit가 모두 잘 출력되었다.

State


공식문서 - State and Lifecycle

공식 문서에 나와있는 클래스 컴포넌트로 구현된 시계 예제를 함수형 컴포넌트로 똑같이 구현할 수 있다.

클래스 컴포넌트함수형 컴포넌트
DidMount()useEffect(...,[])
WillUnmount()useEffect에서 return으로 cleanup
this.state로 초기화, tick()에서 업데이트usetState에서 set할 때 초기화, tick()에서 업데이트



setState()useState()
클래스형 컴포넌트에서 State 관리함수형 컴포넌트에서 State 관리

setState() 사용 시 유의할 점


  • 직접 State를 수정 ❌, 직접 수정하면 렌더가 되지 않아서 화면에 출력되지 않는다.
    // ❌ Wrong
    this.state.comment = 'Hello';
    // ⭕ Correct
    this.setState({comment: 'Hello'});
  • State 업데이트는 비동기적
    • 리액트는 성능을 위해 여러 setState() 호출을 한꺼번에 처리할 수 있다. 이때 기대한 값과 다른 값이 나올 수 있는데, 이는 콜백함수를 사용하여 해결할 수 있다.
    // ❌ Wrong
    this.setState({
      counter: this.state.counter + this.props.increment,
    });
    // ⭕ Correct
    this.setState((state, props) => ({
      counter: state.counter + props.increment
    }));
  • setState()를 호출할 때 리액트는 제공한 객체를 현재 State로 병합한다.

🤔 함수형 vs 클래스
현재는 함수형 컴포넌트에 Hook이 추가되면서 클래스 컴포넌트보다 함수형 컴포넌트가 주로 사용된다.


Lifecycle


공식문서 - React.Component
공식문서 - 생명주기 도표

  • 컴포넌트가 생성되고 사라지는 그 과정을 말한다.
  • 모든 컴포넌트는 생명주기 메서드를 가진다.
  • 컴포넌트는 어떤 변경에 따라 그려질 때마다 자신이 선언해둔 메서드들을 사용한다.
  • 라이프사이클 메서드는 클래스 컴포넌트에서만 사용할 수 있다. 함수형 컴포넌트에서는 Hooks 기능을 사용해서 비슷한 기능을 처리한다.
profile
🙋‍♀️ 안녕하세요! 프론트엔드 개발자입니다.

0개의 댓글