프로젝트 생성, 코드 준비

우선, create-react-app 을 통하여 리액트 프로젝트를 생성하세요.

$ npx create-react-app react-test-tutorial

이미 알고 계실 수도 있겠지만, CRA 로 만든 리액트 프로젝트에는 테스트 환경이 이미 다 준비가 되어있고, 기본 테스트 파일 (App.test.js) 또한 존재 하지요.

한번 해당 파일을 확인해볼까요?

src/App.test.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

it('renders without crashing', () => {
  const div = document.createElement('div');
  ReactDOM.render(<App />, div);
  ReactDOM.unmountComponentAtNode(div);
});

해당 컴포넌트가, 크래쉬 없이 제대로 렌더링이 되었는지 확인을 해줍니다. 이걸 실행하려면, 터미널로 프로젝트의 디렉토리에서 yarn test 를 입력하시면 됩니다.

그러면, 다음과 같은 결과가 나타납니다:

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.672s, estimated 1s
Ran all test suites related to changed files.

Watch Usage
 › Press p to filter by a filename regex pattern.
 › Press t to filter by a test name regex pattern.
 › Press q to quit watch mode.
 › Press Enter to trigger a test run.

다 잘 됐다고 나타나지요.

자, 이제 우리는 아주 간단한 리액트 컴포넌트 3가지를 만들어보도록 하겠습니다.

카운터 만들기

단순히 state 에 있는 값을 + 버튼과 - 버튼을 통하여 변경하는 Counter 컴포넌트 입니다.

src/components/Counter.js

import React, { Component } from 'react';

class Counter extends Component {
  state = {
    value: 1
  }
  onIncrease = () => {
    this.setState(({value}) => ({ value: value + 1 }));
  }
  onDecrease = () => {
    this.setState(({value}) => ({ value: value - 1 }));
  }
  render() {
    const { value } = this.state;
    const { onIncrease, onDecrease } = this;
    return (
      <div>
        <h1>카운터</h1>
        <h2>{value}</h2>
        <button onClick={onIncrease}>+</button>
        <button onClick={onDecrease}>-</button>
      </div>
    );
  }
}

export default Counter;

그리고, 이 컴포넌트를 App 에서 렌더링하세요.

src/App.js

import React, { Component } from 'react';
import Counter from './components/Counter';

class App extends Component {
  render() {
    return (
      <div>
        <Counter />
      </div>
    );
  }
}

export default App;

그리고, yarn start 를 하시면 다음과 같이 나타날 것입니다.

NameForm, NameList 구현하기

이번에는, 이름을 NameForm에 입력해서 등록하면 NameList 에 나타나도록 컴포넌트들을 구현하겠습니다. input 의 상태값은 NameForm 에 넣고, NameList 에서 보여줄 이름 목록에 대한 상태값은 App 에서 NameList 로 props 를 통하여 전달해주도록 설정하겠습니다.

src/components/NameForm.js

import React, { Component } from 'react';

class NameForm extends Component {
  static defaultProps = {
    onSubmit: () => console.warn('onSubmit not defined'),
  }
  state = {
    name: ''
  }
  onChange = (e) => {
    this.setState({
      name: e.target.value
    });
  }
  onSubmit = (e) => {
    const { name } = this.state;
    const { onInsert } = this.props;
    // 이름을 추가하고, name 값 초기화
    onInsert(name);
    this.setState({
      name: ''
    });
    e.preventDefault(); // submit 하면 기본적으로는 페이지가 새로고쳐지게 되는데 이를 방지함
  }
  render() {
    const { onSubmit, onChange } = this;
    const { name } = this.state;
    return (
      <form onSubmit={onSubmit}>
        <label>이름</label>
        <input type="text" value={name} onChange={onChange} />
        <button type="submit">등록</button>
      </form>
    );
  }
}

export default NameForm;

src/components/NameList.js

import React, { Component } from 'react';

class NameList extends Component {
  static defaultProps = {
    names: []
  }

  renderList() {
    const { names } = this.props;
    const nameList = names.map(
      (name, i) => (<li key={i}>{name}</li>)
    );
    return nameList;
  }

  render() {
    return (
      <ul>
        { this.renderList() }
      </ul>
    );
  }
}

export default NameList;

자, 이제 우리가 방금 만든 컴포넌트 두개를 App 에서 렌더링해주겠습니다. 이 과정에서 App 에서 state 값과 onInsert 메소드를 추가해줄게요.

src/App.js

import React, { Component } from 'react';
import Counter from './components/Counter';
import NameForm from './components/NameForm';
import NameList from './components/NameList';

class App extends Component {
  state = {
    names: ['벨로퍼트', '김민준']
  }

  onInsert = (name) => {
    this.setState(({names}) => ({ names: names.concat(name) }));
  }

  render() {
    const { names } = this.state;
    const { onInsert } = this;

    return (
      <div>
        <Counter />
        <hr />
        <h1>이름 목록</h1>
        <NameForm onInsert={onInsert}/>
        <NameList names={names}/>
      </div>
    );
  }
}

export default App;

이러한 결과가 완성 됐나요? 일단 제대로 작동하는지 확인해보세요.

results matching ""

    No results matching ""