LocalStorage를 활용한 목록 관리

이번에는 이전에 구현했던 todo app과 유사하지만 페이지가 refresh 되어도 여전히 목록이 유지되도록 html5의 localStorage를 사용해 볼 것이다.

// actions/index.jsexport const ADD_ITEM = 'ADD_ITEM';
export const TOGGLE_ITEM = 'TOGGLE_ITEM';

export function addItem(text) {
return {
type: ADD_ITEM,
text: text
}
}

export function toggleItem(index) {
return {
type: TOGGLE_ITEM,
index: index
}
}

actions는 addItem과 toggleItem 두 가지 action이 있다. 이전에 구현해왔던 방식과 같다.

addItem() function에서는 input창에 있는 텍스트를 이용해 ADD_ITEM type action으로 만들어주고 toggleItem에서는 index를 이용해 TOGGLE_ITEM type action을 만들어준다.

localStorage는 state가 갱신될 때마다 호출되는 render() function안에서 수정하였는데, ‘items’ key의 내용을 현재 items state로 수정해준다.

localStorage는 {key: ‘value’}형태로 저장되고, value는 문자열만 가능하기 때문에 저장시에 stringify해주고 꺼내서 다시 사용할 때는 parsing해주어야 한다.

items는 각각의 요소를 map함수를 통해서 Item component에 담아 itemList를 만들어주었다.

// containers/AppContainer.jsimport { connect } from 'react-redux';

import App from '../components/App';
import { addItem, toggleItem } from "../actions";

const mapStateToProps = state => {
return state;
};

const mapDispatchToProps = dispatch => {
return {
addItem: (text) => {
dispatch(addItem(text));
},
toggleItem: (index) => {
dispatch(toggleItem(index));
}
}
};

const AppContainer = connect(mapStateToProps, mapDispatchToProps)(App);

export default AppContainer;

AppContainer에서 현재 관리하는 유일한 state인 items를 App component에서 사용하기 위해 state를 그대로 넘겨주었고, store로 action을 dispatch 시켜주는 addItem과 toggleItem을 만들어 App component에 넘겨주었다.

// reducers/index.jsimport { ADD_ITEM, TOGGLE_ITEM } from '../actions/';

const defaultState = {
items: JSON.parse(localStorage.getItem('items')) || []
};

function app(state = defaultState, action) {
switch (action.type) {
case ADD_ITEM:
return {
items: [
...state.items,
{
text: action.text,
done: false
}
]
};
case TOGGLE_ITEM:
return {
items: [
...state.items.slice(0, action.index),
Object.assign({}, state.items[action.index], {
done: !state.items[action.index].done
}),
...state.items.slice(action.index + 1)
]
};
default:
return state;
}
}

export default app;

reducer에서는 Add_ITEM action이 들어왔을 경우 parameter로 전달받은 text를 이용해 items에 새로운 item을 추가한 배열을 반환해주고, toggle일 경우 해당 index item의 done을 토글하여 반환해주었다.

또한 defaultState에서 localStorage에 있는 items를 꺼내와 item이 있을 경우 defaultState로 설정하도록 해주었다. 이제 reducer가 생성될 때 localStorage가 defaultState가 된다.

완성된 화면은 다음과 같다. 화면을 refresh하더라도 목록은 그대로 유지된다.

참고로 현재는 삭제 기능을 구현해놓지 않은 상태이기 때문에 화면을 refresh하더라도 한 번 추가한 목록을 지울 수 없는 문제가 있다.

localStorage를 비우기 위해서는 개발자도구의 application tap에 들어가서도 가능하고 또는 console창에 localStorage.clear()를 사용하면 된다.

woohyun