All Articles

Redux로 Counter 앱 만들기

ReduxNativeBase 를 사용하여 카운터 앱을 만들어 봅니다. NativeBase를 사용하니 컴포넌트 UI가 좀더 수려해졌습니다. 그리고 복잡한 앱을 구현할 때에는 Redux가 필수입니다.

리덕스(Redux)를 사용하지 않을 때와 사용할 때의 차이점은 아래 그림이 잘 표현하고 있습니다.



필요한 모듈 설치하기

expo-cli가 설치되어 있지 않으면 아래와 같이 설치한다.

$ npm install expo-cli --global


expo-cli를 사용하여 프로젝트를 생성한다.

$ expo init redux-counter-app
$ cd redux-counter-app


그리고 Reduxreact-redux를 설치한다.

$ npm install redux react-redux --save


마지막으로 NativeBase를 설치한다.

$ npm install native-base --save
$ npm install @expo/vector-icons --save



구현하기

프로젝트의 루트에 세 개의 폴더 reducers, components 를 생성한다.

Redux Reducers 구현

Reducers는 앱에서 필요한 데이터를 반환한다. 여기서는 Counter 값을 반환하는 reducer가 필요하다. reducers 폴더에 countReducer.js 파일을 생성한다.

다음과 같이 하나의 js 파일에 액션과 리듀서를 모두 구현하는 것을 Ducks 구조이라고 한다. Ducks 구조를 사용하면 나중에 코드 관리하기가 편하다.

reducers/countReducer.js

// Default State
const initialState = {
	count: 0
};

// Actions
export const INCREMENT = "Increment";
export const DECREMENT = "Decrement";

// Action Functions
export function increment(){
  return {
    type: INCREMENT
  };
}
export function decrement(){
  return {
    type: DECREMENT
  };
}

// Reducer
function reducer(state = initialState, action) {
  switch (action.type) {
    case INCREMENT: 
      return {
        count: state.count + 1
      }
    case DECREMENT: 
      return {
        count: state.count - 1
      }
  }
  return state;
}

// Exports Default
export default reducer;

INCREMENTDECREMENT 액션은 카운트 값을 계산하여 반환한다.

그 다음은 index.js 파일에서 모든 Reducer를 결합한다. 지금은 하나의 리듀서 countReducer만 있지만, 나중에 리듀서가 여러 개일 경우 유용하다.

reducers/index.js

import { combineReducers } from 'redux';
import countReducer from './countReducer.js';

const allReducers = combineReducers({
  countReducer,
});

export default allReducers;

Redux 컴포넌트 구현

이제 <Counter> 컴포넌트를 구현한다.

components/counter.js

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { Container, Content, Text, Card, Header, Body, Button, Title, CardItem } from 'native-base';
import { increment, decrement } from '../reducers/countReducer';

class Counter extends Component {
	render() {
    return(
      <Container>
        <Header>
          <Body>
            <Title>Redux Counter</Title>
          </Body>
        </Header>
        <Content padder>
          <Card>
            <CardItem>
              <Text>
                { this.props.state.count }
              </Text>
            </CardItem>
          </Card>
          <Button full onPress= {() => this.props.increment()} style={{marginVertical: 10}}>
            <Text>Increment</Text>
          </Button>
          <Button full dark bordered onPress= {() => this.props.decrement()}>
            <Text>Decrement</Text>
          </Button>
        </Content>
      </Container>
    );
  }
}

// Reducer 데이터를 props로 변환
function mapStateToProps(state){
  return {
    state: state.countReducer
  };
}

// Actions을 props로 변환
function matchDispatchToProps(dispatch){
  return bindActionCreators({
    increment: increment,
    decrement: decrement
  }, dispatch);
}

export default connect(mapStateToProps, matchDispatchToProps)(Counter);

Redux Store 구현

마지막으로 App.js 파일에 store를 만들어야 한다. Redux에 대한 기본 개념은 Redux 공식 문서를 참고한다. App.js 파일을 아래와 같이 수정한다.

App.js

import React, { Component } from 'react';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import allReducers from './reducers';
import Counter from './components/counter.js';

const store = createStore(allReducers);

export default class App extends Component{
  render(){
    return(
      <Provider store={store}>
        <Counter />
      </Provider>
    );
  }
}



실행하기

앱을 실행하고 확인해보자.

$ npm start


여기까지 읽어주셔서 감사합니다.



같이 읽으면 좋은 글:


Sponsored ( Powered by dclick )
DCLICK: An Incentivized Ad platform by Proof of Click - 스팀 기반 애드센스를 소개합니다.

안녕하세요 스티미언 여러분. 오늘 여러분께 스팀 블록체인 기반 광고 플랫폼 DCLICK을 소개…

Published 12 Jan 2019

안피곤의 블로그입니다.