다음 상태 관리가 Redux를 중지하고 unstated로 만드는 이유



react native에서 global State의 관리는 무엇을 사용하고 있습니까? redux입니까? mobx입니까?
둘 다 견고한 라이브러리이지만, 기술량이 많고 학습량도 많습니다.
지금 react를 사용하고 계신 분, 새로 들어온 사람, redux에 대해 이것이 있습니까?
react 초보자에게는 위의 두 가지가 엄격합니다. . .
지금, 해외에서는 군군 늘어나고 있는 초경량 state 관리 라이브러리 「unstated」 사용해 보지 않겠습니까?
global state를 setState로 변경하기 때문에 학습 비용이 매우 낮습니다.
나는 redux에서 unstated로 갈아서 개발 공수가 절반이되었다.
매우 추천합니다.

unstated란?


  • React 표준의 ContextAPI를 매우 얇게 확장한 라이브러리.
  • 학습 비용이 낮고 간단하고 프로토 타입을 만드는 데 적합합니다.
  • 단지 400행으로 쓰여지고, 타사 라이브러리를 사용하지 않고 순수한 react만으로 쓰여져 있다.
  • react만으로 쓰여지기 때문에 테스트가 간단하고 베테랑 엔지니어에게는 이것이 기쁘다.
  • store 영속화를 위한 unstated-persist(느리지만,,) 디버깅을 위한 unstated-debug 등 에코시스템이 충실하다.

  • 실제로 사용해 보자.



    다음은 순수한 react로 작성된 카운터 앱이다. 아직 unstated는 들어 있지 않다.
    class Counter extends React.Component {
      state = { count: 0 }
      increment = () => {
        this.setState({ count: this.state.count + 1 })
      }
      decrement = () => {
        this.setState({ count: this.state.count - 1 })
      }
      render() {
        return (
          <View>
            <Text>{this.state.count}</Text>
            <Text onClick={this.decrement}>-</Text>
            <Text onClick={this.increment}>+</Text>
          </View>
        )
      }
    }
    

    위의 코드를 unstated를 사용하여 View와 로직을 분리해 보자.



    unstated에는 3개의 개념이 있다. react의 contextAPI를 만진 적이 있다면 즉시 익숙해진다.

    1.Container
    global state를 기술하는 컴퍼넌트. redux와 mobx의 이야기
    글로벌 상태 변경 및 보관을 담당.
    즉, 거대한 JSON과 그 JSON을 변경하는 메소드 군
    setState에서 unstated store 내용의 JSON을 다시 씁니다.

    2.Subscribe
    Container의 메소드나 State를 Subscribe로 둘러싸인 컴퍼넌트에 건네준다.

    3.Provider
    Provider로 둘러싸인 컴퍼넌트 중에서 Subscribe를 사용할 수 있도록 하는 메소드.

    unstaed 를 사용하여 작성한 예



    순수한 react처럼 쓸 수 있다.
    import React from 'react'
    import { Provider, Subscribe, Container } from 'unstated'
    import {Text, View} from 'react-native'
    
    class CounterContainer extends Container {
      state = {
        count: 0
      }
    
      increment() {
        this.setState({ count: this.state.count + 1 })
      }
    
      decrement() {
        this.setState({ count: this.state.count - 1 })
      }
    }
    
    function Counter() {
      return (
        <Subscribe to={[CounterContainer]}>
          {counter => (
            <View>
              <Text onClick={() => counter.decrement()}>-</Text>
              <Text>{counter.state.count}</Text>
              <Text onClick={() => counter.increment()}>+</Text>
            </View>
          )}
        </Subscribe>
      )
    }
    
    export default App = () => (
      <Provider>
        <Counter />
      </Provider>
    )
    

    테스트도 매우 간단



    unstated는 순수한 react 컴포넌트이므로, 다음과 같이 매우 간단하게 테스트를 쓸 수 있다.
    수석 엔지니어에게는 이것이 기쁩니다!
    test('counter', async () => {
      let counter = new CounterContainer()
      assert(counter.state.count === 0)
    
      await counter.increment()
      assert(counter.state.count === 1)
    
      await counter.decrement()
      assert(counter.state.count === 0)
    })
    

    조금 불행한 곳.



    unstated에서는 Subscribe 외부에서는 container 메서드를 사용할 수 없습니다.
    즉, componentDidMout 라든지 안에서, unstated 의 state 를 변경하기 위해서는 한가지 궁리할 필요가 있다.

    즉 HOC를 사용할 필요가 있다.
    다음과 같이 컴포넌트를 Subscribe로 둘러싸는 것이 일반적인 사용법이다.
    class Counter extends Component {
      componentDidMount() {
        this.props.counter.increment()
      }
    
      render() {
        const { counter } = this.props
        return(
          <View>
            <Text onClick={() => counter.decrement()}>-</Text>
            <Text>{counter.state.count}</Text>
            <Text onClick={() => counter.increment()}>+</Text>
          </View>
        )
      }
    }
    
    const CounterWrapper = () => (
      <Subscribe to={[CounterContainer]}>
        {counter => <Counter counter={counter} />}
      </Subscribe> 
    )
    
    export default CounterWrapper
    

    react navigationn과 함께 사용할 때는 HOC의 이름으로 routing에 매핑됩니다.



    만약 unstated와 react-navigation을 사용하여 화면이 새하얗게 되는 버그가 나오면 이름이 올바르게 import되어 있는지 확인하자. HOC를 사용하면, react navigation에서는, 화면이 새하얗게 되는 버그가 일어나기 쉽다. HOC react navigation에서 구그하고 해결하자.

    다음은 올바른 예입니다.
    const CounterWrapper = () => (
      <Subscribe to={[CounterContainer]}>
        {counter => <Counter counter={counter} />}
      </Subscribe>
    )
    
    export const HomeStack = createStackNavigator({
      CounterWrapper,
      ScreenB,
      ScreenC,
    })
    

    좋은 웹페이지 즐겨찾기