본문 바로가기

React&React-Native/React

[#. React] React + Redux + hook을 사용해서 Counter 만들기

반응형

 

 

 

 

 

기본적으로 Redux 사용을 익히기 위해 서버 없이 react로만 counter를 만들어보자

일단 react를 시작하기 전에 node가 설치되어 있어야 한다

nodejs.org/ko/

 

Node.js

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

nodejs.org

 

 

설치했으면 react project를 생성해보자

 

npx creact-react-app react-project

 

 

npm install react-router-dom --save
npm install react-redux --save
npm install redux --save
npm install antd --save
npm install styled-components --save

 

redux와 라우팅 관련, 템플릿, css 라이브러리 설치

 

 

 

 

@antd 사용이 안 될 경우

 

프로젝트/src/App.js 파일로 가면 아래처럼 css 파일을 import하고 있는 것을 볼 수 있다

 

import './App.css';

 

프로젝트/src/App.css 파일에 아래 코드를 추가한다

 

@import '~antd/dist/antd.css';

 

 

 

 

실행 명령어

 

npm run start

 

 

 

 

함수형 컴포넌트, hook을 사용하기 때문에

mapPropsToState, mapDispatchToState 대신에

useSelector, useDispatch를 사용할 것이다

 

 

 

① View 페이지 생성

 

src/components/views/LandingPage/LandingPage.js

 

import React from 'react';
import { PlusCircleOutlined, MinusCircleOutlined } from '@ant-design/icons';
import styled from 'styled-components';

const LandingTemplate = styled.div`
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  margin-top: 100px;

  button {
    width: 200px;
    height: 50px;
    margin-right: 10px;
  }
`;

function LandingPage() {
  return (
    <LandingTemplate>
      <div>
        <h1></h1>
      </div>
      <button><PlusCircleOutlined />1</button>
      <button><MinusCircleOutlined />1</button>
    </LandingTemplate>
  )
}

export default LandingPage;

 

 

 

② Router 세팅

 

src/App.js

 

import logo from './logo.svg';
import './App.css';
import { BrowserRouter, Route, Switch } from "react-router-dom";
import LandingPage from "./components/views/LandingPage/LandingPage";

function App() {
  return (
    <BrowserRouter>
       <Switch>
         <Route exact={true} path="/" component={LandingPage} />
       </Switch>
     </BrowserRouter>
  );
}

export default App;

 

 

 

③ Action 세팅

 

⑴ src/actions/types.js

 

export const INCREMENT = 'counter/increment';
export const DECREMENT = 'counter/decrement';

 

⑵ src/actions/counter.js

 

import { INCREMENT, DECREMENT } from './types';

export const increment = () => ({
  type: INCREMENT
})

export const decrement = () => ({
  type: DECREMENT
})

export const initialState = {
  number: 0
}

 

Chrome에서 Redux 스토어를 확인해 보면 counter에 { number: 0 }로 initialState가 들어가 있다

 

 

 

④ Reducer 세팅

 

⑴ src/reducers/counter.js

 

import { INCREMENT, DECREMENT } from '../actions/types';
import { initialState } from '../actions/counter';

export default function(state=initialState, action) {
  switch(action.type) {
    case INCREMENT:
      return {...state, number: state.number + 1}
    case DECREMENT:
      return {...state, number: state.number - 1}
    default:
      return state;
  }
}

 

⑵ src/reducers/index.js

 

import { combineReducers } from 'redux';
import counter from './counter';

const rootReducer = combineReducers({
  counter,	// ⑴
});

export default rootReducer;

 

⑴ Redux Store에 저장되는 이름

 

 

 

⑤ Store 세팅

 

src/index.js

 

import { createStore } from 'redux';
import { Provider } from 'react-redux';
import rootReducer from './reducers';

const devTools =
  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__();
const store = createStore(rootReducer, devTools);

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);

 

 

Store 세팅, Redux 크롬 확장 프로그램 다운은 아래 링크에서 자세히 확인 가능

developer0809.tistory.com/17?category=902243

 

[#React] React 프로젝트에 Redux 사용하기(초기 설정)

Redux를 사용할 거기 때문에 세팅해 보겠습니다 npm install redux npm install react-redux npm install redux-actions 폴더, 파일 생성해 주세요 src ㄴstore  ㄴmodules ㄴindex.js ㄴtest.js ① src/store/mo..

developer0809.tistory.com

 

 

 

⑥ View 수정

View에서 Action을 dispatch해서 state 변경하기

 

components/views/LandingPage/LandingPage.js

 

import React from 'react';
import { PlusCircleOutlined, MinusCircleOutlined } from '@ant-design/icons';
import styled from 'styled-components';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement } from '../../../actions/counter';

const LandingTemplate = styled.div`
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  margin-top: 100px;

  h1 {

  }

  button {
    width: 200px;
    height: 50px;
    margin-right: 10px;
  }
`;

function LandingPage() {

  const num = useSelector(state => state.counter.number)   // ⑴
  const dispatch = useDispatch();

  const onIncrease = () => {
    dispatch(increment())
  }

  const onDecrease = () => {
    dispatch(decrement())
  }

  return (
    <LandingTemplate>
      <div>
        <h1>{num}</h1>
      </div>
      <button onClick={onIncrease}><PlusCircleOutlined />1</button>
      <button onClick={onDecrease}><MinusCircleOutlined />1</button>
    </LandingTemplate>
  )
}

export default LandingPage;

 

⑴ reducers/index.js에서 combine한 reducer명을 기준으로 가져온다

 

 

 

 

 

counter 완성

 

 

 

 

 

 

 

 

@ Flow 정리 

action: 중복 없는 action 정의
reducer: state에 데이터 set, state 변경

 

 

➊ View
action을 import해서 useDispatch()를 이용해서 dispatch
useSelector()를 이용해서 state 값을 가져옴

 

ex)

const num = useSelector(state => state.counter.number);

const dispatch = useDispatch();
dispatch(increment());

 

 

➋ Action
중복이 없는 액션 타입 리턴

 


➌ Reducer
액션명과 동일한 reducer를 찾아 매칭
state에 데이터 set, state 변경

 

 

 

 

 

반응형