2019. 9. 1. 22:20

0. 디렉터리 구성

 

1. 패키지 설치

yarn add redux react-redux redux-actions immutable

 

2-1. input 모듈 생성

//dukcks structure

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

//action types
const SET_INPUT = 'input/SET_INPUT';

//action creator
export const setInput = createAction(SET_INPUT);
// ex: call -> setInput({value:'abc'}) 
// return value -> action object = {type:SET_INPUT, payload:{value:'abc'}}

//initialState
const initialState = Map({
    value:' '
});

//reducer
export default handleActions ({
    [SET_INPUT]: (state, action) => {
        return state.set('value', action.payload)
    }
}, initialState);

 

2-2. todos 모듈 생성

//dukcks structure

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

//action types
const INSERT = 'todos/INSERT';
const TOGGLE = 'todos/TOGGLE';
const REMOVE = 'todos/REMOVE';

//action creators
export const insert = createAction(INSERT);
// ex: call -> insert({id:4, text:'abc', done:'false'}) 
// return value -> action object = {type:INSERT, payload:{id:4, text:'abc', done:'false'}}

export const toggle = createAction(TOGGLE);
// ex: call -> toggle(1) 
// return value -> action object = {type:toggle, payload:1}

export const remove = createAction(REMOVE);
// ex: call -> remove(2) 
// return value -> action object = {type:remove, payload:2}

//initialState
const initialState = List([
    Map({id:0, text:'todo1', done:true}),
    Map({id:1, text:'todo22', done:false}),
    Map({id:2, text:'todo333', done:false})
]);

//reducer
export default handleActions({
    [INSERT] : (state,action) => {
        console.dir(action);
        return state.push(Map({            
            id:action.payload.id,
            text:action.payload.text,
            done:action.payload.done
        }));
    },
    [TOGGLE]: (state,action) => {
        console.dir(action);
       // const {payload:id} = action;
        //List의 내장함수 get
       // console.dir(action);
        const index = state.findIndex(todo => todo.get('id') === action.payload);
        //List의 내장함수 update
        return state.update(index, item=>item.set('done',!item.get('done')));
    },
    [REMOVE]:(state,action) => {
        const {payload:id} = action;
        const index = state.findIndex(todo => todo.get('id') === id);
        return state.delete(index);
    }
}, initialState);

 

2-3. 모듈 index 생성

import input from './input';
import todos from './todos';
import {combineReducers} from 'redux';

export default combineReducers({
    input,
    todos
});

//  state { 
//     input : Map({ value:' ' }), 
//     todos :[ Map({id:0,text:" ",done: }), Map({...}), ...]
// }

 

3. 스토어 생성

import React from 'react';
import ReactDOM from 'react-dom';
import './styles/main.scss';
import App from './components/App';
import * as serviceWorker from './serviceWorker';

//creating store
import modules from './modules';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
const store = createStore(modules, window.devToolsExtension && window.devToolsExtension());

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

serviceWorker.unregister();

 

4-1. TodoInputContainer 생성

import React, {Component} from 'react';
import TodoInput from '../components/TodoInput';

import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';

import * as inputActions from '../modules/input';
import * as todosActions from '../modules/todos';

const mapStateToProps = (state) => ({
    value:state.input.get('value')
});

const mapDispatchToProps = (dispatch) => ({
    InputActions : bindActionCreators(inputActions, dispatch),
    TodosActions : bindActionCreators(todosActions, dispatch)
});

class TodoInputContainer extends Component {
    id=1

    getId = () => {
        return ++this.id;
    };
	
    handleChange = (e) => {
        this.props.InputActions.setInput(e.target.value);	//setInput() : action creator
    };

    handleInsert = () => {
        const todo = {
            id: this.getId(),
            text:this.props.value,
            done:false
        };
        this.props.TodosActions.insert(todo);			//insert() : action creator	
        this.props.InputActions.setInput(' ');			//setInput() : action creator
    };


    render() {
        return (
            <div>
                <TodoInput
                    onChange={this.handleChange}
                    onInsert={this.handleInsert}
                    value={this.props.value}
                />
            </div>
        );
    }
};

export default connect(mapStateToProps, mapDispatchToProps)(TodoInputContainer);

 

4-2. TodoListContainer 생성

import React, {Component} from 'react';
import TodoList from '../components/TodoList';

import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';

import * as todoActions from '../modules/todos';

const mapStateToProps = (state) => ({
    todos:state.todos
});

const mapDispatchToProps = (dispatch) => ({
    TodoActions : bindActionCreators(todoActions, dispatch)
});

class TodoListContainer extends Component {
    handleToggle = (id) => {
        this.props.TodoActions.toggle(id);  //toggle() : action creator
    }
    handleRemove = (id) => {
        this.props.TodoActions.remove(id);  //remove() : action creator
    }

    render() {
        return (
            <div>
                <TodoList
                    todos={this.props.todos}
                    onToggle={this.handleToggle}
                    onRemove={this.handleRemove}
                />
            </div>
        );
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(TodoListContainer);

 

5. TodoList 수정

import React, { Component } from 'react';
import TodoItem from '../TodoItem';

class TodoList extends Component {
    
    render() {
        const { todos, onToggle, onRemove } = this.props;
        const todoList = todos.map((todo) => {
            return (
                <TodoItem
                    key={todo.get('id')}
                    done={todo.get('done')}
                    onToggle={() => onToggle(todo.get('id'))}
                    onRemove={() => onRemove(todo.get('id'))}
                >
                    {todo.get('text')}
                </TodoItem>
            )
        })
        return (
            <div>
                {todoList}
            </div>
        );
    }
}

export default TodoList;

 

6. App.js 수정

import React, { Component } from 'react';
import PageTemplate from './PageTemplate';
import TodoInputContainer from '../containers/TodoInputContainer';
import TodoListContainer from '../containers/TodoListContainer';


class App extends Component {

    render() {
       
        return (
            <div>
                <PageTemplate>
                    <TodoInputContainer />
                    <TodoListContainer />
                </PageTemplate>
            </div>
        );
    };
};

export default App;

'Javascript > projects' 카테고리의 다른 글

blog 1-1  (0) 2019.09.05
Counter (2) : 멀티 카운터  (0) 2019.08.29
Counter (1) : 카운터 만들기  (0) 2019.08.29
Todo-list (4) : 리렌더링 최적화 하기  (0) 2019.08.29
Todo-list (3) : 데이터 추가, 수정, 삭제  (0) 2019.08.29
Posted by yongminLEE