본문 바로가기

프로그램 강좌

[react.js]immer 사용방법

immer.js 쓰는 이유?

단순히 state의 1depth 정도라면 손쉽게 변화가 가능하지만, 하위 depth가 엄청나게 많아진다면 정말 불편해집니다.

(불변성 어쩌구 하는데 솔직히 이 말은 이해는 했지만, 참 안와닿고 먼 단어네요.
그냥 데이터 안날라가고 원하는 부분만 업데이트 해주기가 쉽지 않다는 말로 해석하시면 될듯요.)

그럴때 immer.js를 써주면 손쉽게 바꿀 수 있습니다.

immer 설치방법

yarn add immer


immer 사용방법

기존 이런 소스가 있다고 합시다. 아주아주 간단하게 카운터를 만들었습니다.


App.js

import React, { Component } from 'react';

class App extends Component {
  state = {
    counter: {
      num: 0
    }
  };
  handleClick = () => {
    this.setState({
      ...this.state.counter,
      num: this.state.counter.num++
    });
  };
  render() {
    const { num } = this.state.counter;
    const { handleClick } = this;
    return (
      <div>
        <h1>{num}</h1>
        <button onClick={handleClick}>+</button>
      </div>
    );
  }
}

export default App;

handleClick 부분 정말 지져분하죠? 예제니까 2depth까지 해놨는데, 더 복잡했을겁니다.

이제 immer 를 사용해보겠습니다. handleClick 부분만 바꾸면 되겠네요.


App.js

import React, { Component } from 'react';
import produce from 'immer';

class App extends Component {
  state = {
    counter: {
      num: 0
    }
  };
  handleClick = () => {
    this.setState(
      produce(draft => {
        draft.counter.num++;
      })
    );
  };
  render() {
    const { num } = this.state.counter;
    const { handleClick } = this;
    return (
      <div>
        <h1>{num}</h1>
        <button onClick={handleClick}>+</button>
      </div>
    );
  }
}

export default App;

좀더 복잡하게 해본다면 이렇게도 써볼 수 있습니다.

App.js

import React, { Component } from 'react';
import produce from 'immer';

class App extends Component {
  state = {
    counter: {
      num: 0,
      arr: [
        {
          number: 1
        }
      ],
      input: ''
    }
  };
  count = 1;
  handleClick = () => {
    this.setState(
      produce(draft => {
        draft.counter.num++;
        draft.counter.arr.push({
          number: ++this.count
        });
        draft.counter.input = 'test';
      })
    );
  };
  render() {
    const { num, arr, input } = this.state.counter;
    const { handleClick } = this;
    return (
      <div>
        <h1>{num}</h1>
        <button onClick={handleClick}>+</button>
        <ul>
          {arr.map(item => (
            <li>{item.number}</li>
          ))}
        </ul>
        <p>{input}</p>
      </div>
    );
  }
}

export default App;

 


더 복잡한 구조에서 훨씬 더 빛을 발하겠죠?

728x90