[리액트공부] 3. 컴포넌트

kkado·2022년 7월 29일
0

리다기

목록 보기
4/16
post-thumbnail

리액트를 사용한 애플리케이션의 인터페이스를 설계할 때 사용자가 볼 수 있는 요소는 컴포넌트로 구성되어 있다.

컴포넌트는 단순한 템플릿 이상으로, UI를 만들어주는 것은 물론, 컴포넌트가 화면에 나타날 때, 사라질 때, 변화가 일어날 때 주어진 작업을 처리할 수 있고, 특별한 기능을 만들어 붙일 수도 있다.

컴포넌트는 함수형과 클래스형, 두 가지 방식으로 작성할 수 있다.

함수형 컴포넌트

function App() {
  const name = "리액트";
  return (
    <>
      <h1>{name}</h1>
    </>
  );
}

함수형 컴포넌트는 클래스형에 비해 선언하기가 매우 편하고, 메모리를 덜 사용한다. 그리고 프로젝트 빌드 후 배포할 때에도 파일 크기가 더 작다. (하지만 사실상 별 차이 없다.)

그리고 함수형 컴포넌트의 단점은 state와 라이프사이클 API 사용이 불가능하다는 점이었는데 리액트 v16.8 업데이트 이후 Hooks 기능이 도입되면서 해결되었다.

리액트 공식 매뉴얼에서는 컴포넌트를 작성할 때 함수형 컴포넌트+Hooks를 사용하도록 권장하고 있다.

클래스형 컴포넌트

class App extends Component {
  render() {
    const name = "리액트";
    return <h1>{name}</h1>;
  }
}

클래스형 컴포넌트의 경우, 이후 배울 state 기능과 라이프사이클 기능을 사용할 수 있고, 임의 메서드를 정의할 수 있다.

컴포넌트 내보내기, 불러오기

내가 MyComponent.js 컴포넌트를 작성했다고 했을 때 이를 다른 컴포넌트에서 사용하고 싶다면, 먼저 MyComponent.js 파일의 하단에

export default MyComponent;

를 작성해 주고, MyComponent를 가져오고 싶은 코드의 상단에

import Mycomponent from `./MyComponent`;

와 같이 작성할 수 있다. 그리고 불러와서 사용할 수 있다.

const App = () => (
    return <MyComponent />
)

화살표 함수와 function 함수

화살표 함수(arrow function)은 ES6 문법에서 함수를 표현하는 새로운 방식이다. 이 문법은 주로 함수를 파라미터로 전달할 때 유용하다.

setTimeout(function() {
    console.log("hello");
}, 1000);

setTimeout(() => {
    console.log("hello")
}, 1000);

두 함수는 비슷해 보이지만, 조금 다르다. 다음 코드를 보면 :

import React from "react";

function BlackDog() {
    this.name = "흰둥이";
    return {
        name: "검둥이",
        bark: function() {
            console.log(this.name + ': 멍멍!');
        }
    }
}

function WhiteDog() {
    this.name = "흰둥이";
    return {
        name: "검둥이",
        bark: () => {
            console.log(this.name + ': 멍멍!');
        }
    }
}

const blackDog = new BlackDog();
blackDog.bark(); // 검둥이 : 멍멍!

const whiteDog = new WhiteDog();
whiteDog.bark(); // 흰둥이 : 멍멍!

서로 가리키고 있는 this 값이 다르다. 일반 function 함수는 자신이 종속된 개체를 가리키고, 화살표 함수는 자신이 종속된 인스턴스 를 가리킨다.

props

props는 properties의 줄임 표현이다. 컴포넌트의 속성을 설정할 때 사용한다.
props 값은 함수의 파라미터로 받아 와서 사용할 수 있다.

const MyComponent = (props) => {
  return <div>제 이름은 {props.name}입니다.</div>;
};
const App = () => {
    return <MyComponent name="React" />;
};

defaultProps 설정

만약 props 값을 따로 지정하지 않았을 때 보여줄 기본값을 설정하는 defaultProps가 있다.

defaultProps는 다음과 같이 설정한다.

const MyComponent = (props) => {

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

MyComponent.defaultProps = {
    name: "기본값"
};

children

태그 사이의 내용을 보여주는 props가 children 이다.

const MyComponent = (props) => {
  return (
    <div>
      <h1>{props.name}</h1>
      <h2>{props.children}</h2>
    </div>
  );
};

const App = () => {
  return <MyComponent>리액트</MyComponent>;
};

<h2> 태그에 '리액트' 가 나타나게 된다.

비구조화 할당 문법

const MyComponent = (props) => {
    const {name, children} = props;
  return (
    <div>
      <h1>{name}</h1>
      <h2>{children}</h2>
    </div>
  );
};

객체에서 값을 추출하는 문법을 비구조화 할당(destructuring assignment) 이라고 하며, 구조 분해 문법이라고도 불린다.

함수의 파라미터 부분에서도 사용할 수 있다.

const MyComponent = ({name, children}) => {
  return (
    <div>
      <h1>{name}</h1>
      <h2>{children}</h2>
    </div>
  );
};

propTypes

필수로 지정해 주어야 하는 props나 props의 type을 지정할 때에 propTypes를 사용한다.

import propTypes from 'prop

const MyComponent = ({name, children}) => {
  return (
    <div>
      <h1>{name}</h1>
      <h2>{children}</h2>
    </div>
  );
};

MyComponent.propTypes = {
    name: propTypes.string
}

name을 문자열(string) 형태로 전달해야 한다는 것을 의미한다.
타입명 뒤에 .isRequired를 붙이면 필수 props로 지정할 수 있다.

state

state는 컴포넌트 내부에서 바뀔 수 있는 값을 의미한다.

props는 컴포넌트가 사용되는 과정에서 부모 컴포넌트가 설정해 주는 값이며 컴포넌트 자신은 props를 읽기 전용으로만 사용할 수 있고 변경할 수 없다.

리액트에는 두 가지 종류의 state가 있는데, 하나는 클래스형 컴포넌트가 지니고 있는 stat이고 다른 하나는 함수형 컴포넌트에서 useState라는 함수를 통해 사용하는 state이다.

클래스형 컴포넌트의 state

다음과 같이 코드를 작성한다.

export default class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = {
      number: 0,
    };
  }
  render() {
    const { number } = this.state;
    return (
      <div>
        <h1>{number}</h1>
        <button
          onClick={() => {
            this.setState({ number: number + 1 });
          }}
        >
          +1
        </button>
      </div>
    );
  }
}

컴포넌트에 state를 설정하는 부분이다.

constructor(props) {
    super(props);
    this.state = {
      number: 0,
    };
  }

위와 같이 constructor 메서드를 작성하고, 안에 반드시 super(props)를 호출해 주어야 한다. 이 함수가 호출되면 현재 클래스형 컴포넌트가 상속하고 있는 (extends) 리액트의 Component 클래스가 지닌 생성자 함수를 호출해 준다.

그 다음에는 this.state 값에 초기값을 설정해 준다.

컴포넌트의 state는 객체 형식이어야 한다.

render() {
    const { number } = this.state;
    return (
      <div>
        <h1>{number}</h1>
        <button
          onClick={() => {
            this.setState({ number: number + 1 });
          }}
        >
          +1
        </button>
      </div>
    );
  }

render 함수에서 현재 state를 조회할 때에는 this.state를 지정하면 된다.
그리고 버튼의 onClick 이벤트로 this.setState 함수를 사용했는데, 이 함수가 state 값을 바꿀 수 있게 해 준다.

잘 동작하고 있는 모습.

constructor에서 state 값 빼내기

export default class Counter extends Component {
  state = {
    number: 0,
    fixedNumber: 0
  };
  
  render() {
    const { number } = this.state;
    return (
      <div>
        <h1>{number}</h1>
        <button
          onClick={() => {
            this.setState({ number: number + 1 });
          }}
        >
          +1
        </button>
      </div>
    );
  }
}

위와 같이 state를 작성해 주는 것이 더 간결하다.

setState가 끝난 후 특정 작업 실행

		onClick={() => {
            this.setState(
              {
                number: number + 1,
              },
              () => {
                console.log("방금 setState가 호출되었습니다.");
                console.log(this.state);
              }
            );
          }}

setState의 두 번째 파라미터로 콜백 함수를 등록하여 작업을 처리할 수 있다.

함수형 컴포넌트의 useState

16.8 이후부터 useState 함수를 이용하여 함수형 컴포넌트에서도 state를 사용할 수 있게 되었다.

이 과정에서 Hooks 라는 것을 사용하게 된다. (챕터 8 내용)

const Say = () => {
    const [message, setMessage] = useState('');
    const onClickEnter = () => {
        setMessage("안녕하세요");
    };

    return (
        <div>
            <h1>{message}</h1>
            <button onClick={onClickEnter}>입장</button>
        </div>
    );
}

const [message, setMessage] = useState(''); 부분을 잘 보자.

함수를 호출하면 배열이 반환되는데, 배열의 첫 번째 원소는 현재 상태이고 두 번째 원소는 상태를 바꾸어 주는 함수이다. 이 함수를 세터(setter) 함수라고 한다.

이름은 자유롭게 지을 수 있는데 세터 함수는 set+(변수명)으로 짓는 것이 일반적이다.

버튼을 클릭하면 onClickEnter 함수, 곧 setMessage 함수가 호출되어 message 값을 '안녕하세요' 로 바꾸고, 곧이어 h1 태그에서 화면에 나타나게 된다.

state 사용에 있어 주의사항

state 값을 바꾸어야 할 때는 setState 혹은 useState를 통한 세터 함수를 사용해야 한다.

const [object, setObject] = useState({a: 1, b: 1});
object.b = 2;

위와 같은 코드는 잘못된 코드이다.

정리

컴포넌트를 만들고, 내보내고 불러오는 (export, import) 방법과 props, state 사용방법을 배웠다.

또한 function형 함수와 화살표 함수의 문법과 차이에 대해서 알게 되었다.

profile
베이비 게임 개발자

0개의 댓글