본문 바로가기
React

[React] redux 를 이용한 예제 - 떽떽대는 개발공부

by 떽이 2021. 1. 22.

2021/01/21 - [React] - [React] props 전달받기 예제 - 떽떽대는 개발공부

 

[React] props 전달받기 예제 - 떽떽대는 개발공부

react 를 공부하는데 있어 props 값이 기본이지만 이해하는데 어려움이 있었다. 이번엔 컴포넌트 3개를 이용하여 container, input, result 각각 작성하여 props 값 넘기기 예제를 작성해 보았다. 먼저, 아래

ddeck.tistory.com

 

 

 

 

이전 글에서 props 를 이용하여 예제를 만들어 보았다.

동일한 예제를 props 가 아닌 redux - store 를 사용하여 만들어 보았다.

npm install redux react-redux

 

먼저, store 를 사용하기 위해 index.js 에 store 를 만들어 준다.

src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from 'redux';
import { Provider } from 'react-redux';

import rootReducer from '@module/rootReducer';
import BoardContainer from '@BoardNew2/BoardContainer'

// reducer 와 devTool 을 가진 store 생성
const store = createStore(rootReducer);

// Provider 는 자식 컴포넌트 BoardContainer가 store 의 state 를 사용할 수 있도록 해준다.
ReactDOM.render(
  <Provider store={store}>
    <BoardContainer />,
  </Provider>,
  document.getElementById('app')
);

 

store 는 reducer 를 이용하여 생성하는데, 하나의 어플리케이션에서는 하나의 store 만 생성할 수 있으므로 여러개의 reducer 를 사용하기 위해 rootReducer.js 로 모든 리듀서를 감싸준다.

이 예제에서는 하나의 리듀서를 사용하지만, 공부를 위해 rootReducer 를 생성하였다.

src/module/rootReducer.js

import { combineReducers } from 'redux';
import boardNewReducer from '@module/boardNewReducer';

const rootReducer = combineReducers({
    boardNewReducer
});

export default rootReducer;

 

src/module/boardNewReducer.js

// Action Type
const _SAVE = 'DATA_SAVE';

// Action Create Function
export const boardNewSave = (saveData) => (
    console.log('saveData :: ', saveData),
    {
    type: _SAVE,
    inputData: {
        content: saveData
    },
})

// initState
const initialState = {
    inputData: {
        content: ''
    }
}

// Reducer
export default function boardNewReducer(state = initialState, action) {
    switch(action.type) {
        case _SAVE:
            return Object.assign({}, state, {
                inputData: {
                    content: action.inputData.content
                }
            })
        default:
            return state;
    }
}

 

리듀서에서 가장 먼저, 액션 타입을 지정해준다.  타입은 리듀서의 필수 값으로, 타입으로 어떤 액션을 호출할 지 결정할 수 있다.

다음은 컴포넌트 부분이다. (나는 프로젝트 안에 다른 예제도 있어서 컨테이너 안에 BoardNew2 라는 디렉토리를 새로 생성하였다.

src/container/boardNew2/BoardContainer.js

import React from 'react';

import BoardInput from '@BoardNew2/BoardInput'
import BoardResult from '@BoardNew2/BoardResult'

function BoardContainer() {

    return(
        <div>
            <div>
                <BoardInput />
            </div>
            <hr />
            <div>
                <BoardResult />
            </div>
        </div>
    )
}

export default BoardContainer;

 

src/container/boardNew2/BoardInput.js

import React, { useState } from 'react';
import { useDispatch } from 'react-redux';
import { boardNewSave } from '@module/boardNewReducer';

function BoardInput() {
    const [content, setContent] = useState('')
    const dispatch = useDispatch();

    const onSave = () => {
        dispatch(boardNewSave(content))
        setContent('')
    }

    const handleContent = (e) => {
        setContent(e.target.value)
    }

    return (
        <div>
            <div>
                내용: <input type="text" name="content" value={content} onChange={handleContent} />
                <button onClick={onSave}>input</button>
            </div>
        </div>
    );
}

export default BoardInput;

 

먼저, boardInput.js 안에서 content 를 제어해주기 위해 useState를 사용하였다.

그리고 함수형 컴포넌트에서 useDispatch 함수를 사용하기 위해 먼저 dispatch 를 선언해주었다.

input 에 내용이 입력될 때마다 handleContent 로 useState 를 사용하여 content 값을 실시간으로 변경 해주었고

버튼을 클릭하면 리듀서에서 선언 했던 boardNewSave 함수로 dispatch 하고 input 값은 reset 시켜준다.

여기서 reducer를 다시 보면

export const boardNewSave = (saveData) => (
    console.log('saveData :: ', saveData),
    {
    type: _SAVE,
    inputData: {
        content: saveData
    },
})

 

onSave 에서 호출된 리듀서 함수는 이 부분이다.

이 부분에서 inputData 를 매개변수로 전달한 content 로 받아서 action 의 type 을 정해준다.

export default function boardNewReducer(state = initialState, action) {
    switch(action.type) {
        case _SAVE:
            return Object.assign({}, state, {
                inputData: {
                    content: action.inputData.content
                }
            })
        default:
            return state;
    }
}

 

그리고 이 부분에서 정해진 type 에 따라서 받아온 content 값을 어떻게 처리하여 store 에 전달할 지 결정 되는데

이 부분은 순수 함수만 사용 가능하고, state 를 직접적으로 변경하면 안된다고 하여 assign 을 이용하여 기존 state 를 복사하여 사용하였다.

 

src/container/boardNew2/BoardResult.js

import React from 'react';
import { useSelector } from 'react-redux';
 
function BoardResult() {
    const {inputData} = useSelector(state => state.boardNewReducer)

    return(
        <div>
            결과: <input type="text" value={inputData.content} />
        </div>
    )
}

export default BoardResult;

 

그리고 BoardResult 에서 useSelector를 통하여 inputData 를 받아오면 된다.

이로써 어렵게 느껴졌던 redux 예제도 공부 해 보았다.

아직 너무 간단한 예제라 조금 더 복잡한 예제를 공부하며 리덕스에 대한 두려움을 떨쳐야겠다.

 

 

댓글