5-7. 인풋에 상태 연동하기

이번 섹션에서는 인풋에 상태를 연동해보겠습니다. 그러기 위해선, 우선 리덕스 모듈을 만들어야겠지요?

회원가입과 로그인 페이지에서 인풋 내용이 변경 될 때 호출할 변화에 대한 로직을 재사용을 할 수 있도록 모듈을 작성해보겠습니다.

모듈의 이름은 auth 로 정하도록 하고, 두가지의 액션을 만들고 이를 처리하는 코드를 작성해보겠습니다. 첫번째 액션은 특정 폼의 특정 인풋의 값을 변경하는 CHANGE_INPUT 이고, 두번째 액션은 특정 폼을 초기 상태로 설정해주는 INITIALIZE_FORM 입니다.

src/redux/modules/auth.js

import { createAction, handleActions } from 'redux-actions';

import { Map } from 'immutable';

const CHANGE_INPUT = 'auth/CHANGE_INPUT'; // input 값 변경
const INITIALIZE_FORM = 'auth/INITIALIZE_FORM'; // form 초기화

export const changeInput = createAction(CHANGE_INPUT); //  { form, name, value }
export const initializeForm = createAction(INITIALIZE_FORM); // form 

const initialState = Map({
    register: Map({
        form: Map({
            email: '',
            username: '',
            password: '',
            passwordConfirm: ''
        })
    }),
    login: Map({
        form: Map({
            email: '',
            password: ''
        })
    })
});

export default handleActions({
    [CHANGE_INPUT]: (state, action) => {
        const { form, name, value } = action.payload;
        return state.setIn([form, 'form', name], value);
    },
    [INITIALIZE_FORM]: (state, action) => {
        const initialForm = initialState.get(action.payload);
        return state.set(action.payload, initialForm);
    }
}, initialState);

이렇게 작성하면, CHANGE_INPUT 하나로, 각 6개의 인풋들을 처리해 줄 수 있겠지요?

리덕스 모듈을 작성하셨다면, 이를 불러와서 인덱스 파일의 combineReducers 안에 넣어주세요.

src/redux/modules/index.js

import { combineReducers } from 'redux';
import base from './base';
import auth from './auth';

export default combineReducers({
    base,
    auth
});

이제, 로그인 페이지의 인풋값부터 연동해주겠습니다.

Login 리덕스에 연동하기

authActions 를 불러와서 이를 바인딩 시켜주고, handleChange 를 만들어서 이벤트 타겟의 namevalue 에 따라서 아까 만든 changeInput 을 호출해주면 됩니다.

그리고, 렌더링 부분에선, email 과 password 값을 로그인 폼에서 읽어와서 각 인풋의 value 로 전달을 하세요.

src/containers/Auth/Login.js

import React, { Component } from 'react';
import { AuthContent, InputWithLabel, AuthButton, RightAlignedLink } from 'components/Auth';
import { connect } from 'react-redux';
import {bindActionCreators} from 'redux';
import * as authActions from 'redux/modules/auth';

class Login extends Component {

    handleChange = (e) => {
        const { AuthActions } = this.props;
        const { name, value } = e.target;

        AuthActions.changeInput({
            name,
            value,
            form: 'login'
        });
    }

    render() {
        const { email, password } = this.props.form.toJS(); // form 에서 email 과 password 값을 읽어옴
        const { handleChange } = this;

        return (
            <AuthContent title="로그인">
                <InputWithLabel 
                    label="이메일" 
                    name="email" 
                    placeholder="이메일" 
                    value={email} 
                    onChange={handleChange}
                />
                <InputWithLabel 
                    label="비밀번호" 
                    name="password" 
                    placeholder="비밀번호" 
                    type="password" 
                    value={password} 
                    onChange={handleChange}
                />
                <AuthButton>로그인</AuthButton>
                <RightAlignedLink to="/auth/register">회원가입</RightAlignedLink>
            </AuthContent>
        );
    }
}

export default connect(
    (state) => ({
        form: state.auth.getIn(['login', 'form'])
    }),
    (dispatch) => ({
        AuthActions: bindActionCreators(authActions, dispatch)
    })
)(Login);

그렇게 복잡하진 않았지요? 이제 회원가입 페이지도 리덕스와 연동을 해줍시다.

Register 리덕스 연동하기

Register 을 연동하는건, Login 을 연동하는것과 매우 비슷합니다. 차이점이 있다면, login 이 들어갈 자리에 register 가 들어간다는 점 입니다.

src/components/Register.js

import React, { Component } from 'react';
import { AuthContent, InputWithLabel, AuthButton, RightAlignedLink } from 'components/Auth';
import { connect } from 'react-redux';
import {bindActionCreators} from 'redux';
import * as authActions from 'redux/modules/auth';


class Register extends Component {

    handleChange = (e) => {
        const { AuthActions } = this.props;
        const { name, value } = e.target;

        AuthActions.changeInput({
            name,
            value,
            form: 'register'
        });
    }

    render() {
        const { email, username, password, passwordConfirm } = this.props.form.toJS();
        const { handleChange } = this;

        return (
            <AuthContent title="회원가입">
                <InputWithLabel 
                    label="이메일"
                    name="email"
                    placeholder="이메일" 
                    value={email} 
                    onChange={handleChange}
                />
                <InputWithLabel 
                    label="아이디" 
                    name="username" 
                    placeholder="아이디" 
                    value={username} 
                    onChange={handleChange}
                />
                <InputWithLabel 
                    label="비밀번호" 
                    name="password" 
                    placeholder="비밀번호"
                    type="password" 
                    value={password} 
                    onChange={handleChange}
                />
                <InputWithLabel 
                    label="비밀번호 확인" 
                    name="passwordConfirm" 
                    placeholder="비밀번호 확인" 
                    type="password" 
                    value={passwordConfirm}
                    onChange={handleChange}
                />
                <AuthButton>회원가입</AuthButton>
                <RightAlignedLink to="/auth/login">로그인</RightAlignedLink>
            </AuthContent>
        );
    }
}

export default connect(
    (state) => ({
        form: state.auth.getIn(['register', 'form'])
    }),
    (dispatch) => ({
        AuthActions: bindActionCreators(authActions, dispatch)
    })
)(Register);

코드를 다 작성하셨다면, 로그인페이지와, 회원가입페이지에서 인풋에 입력이 제대로 되는지 테스팅을 해보시고, 입력이 제대로 됐다면, 리덕스 개발자 도구를 열어서 액션이 제대로 디스패치 되고 있는지도 확인해보세요.

로그인 페이지에서 인풋을 입력한 상태로, 회원가입을 갔다가, 다시 로그인에 돌아오면 인풋값이 그대로 남아있습니다. 현재 상태값들이 리덕스 스토어에 남아있기 때문에 컴포넌트가 언마운트가 되어도 값이 초기화되지 않습니다.

따라서, 컴포넌트가 언마운트 될 때, 아까 만들었던 initializeForm 이 호출되도록 코드를 작성하겠습니다.

Login 과 Register 컴포넌트 내에 다음 코드를 삽입하세요.

src/containers/Auth/Login.js - componentWillUnmount

    componentWillUnmount() {
        const { AuthActions } = this.props;
        AuthActions.initializeForm('login')
    }

src/containers/Auth/Register.js - componentWillUnmount

    componentWillUnmount() {
        const { AuthActions } = this.props;
        AuthActions.initializeForm('register')
    }

이제, 로그인 페이지의 상태도 어느정도 관리가 되고 있습니다. 다음 차례는 우리가 초반에 만들었던 로그인 API 를 사용해볼 차례입니다.

results matching ""

    No results matching ""