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 |