1. store에 thunk 추가
import { createStore, applyMiddleware, compose } from 'redux';
import { thunk } from 'redux-thunk';
import rootReducer from './reducers';
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
rootReducer,
composeEnhancers(applyMiddleware(thunk))
);
export default store;
2. thunk creator 작성 : 이때 보통의 action은 객체 형태지만 thunk 는 action을 함수로 보내준다.
따라서 비동기 통신 등 여러가지 형태로 운용할 수 있다. 어떤 여러가지 형태인지는
밑에 다시 적어보았다.
//thunk action creator page
//async => setTimeout()
import {
ADD_TODO,
REMOVE,
addTodoActionCreator,
removeTodoActionCreator
} from "../actions";
const TODO_MAX_COUNT = 3 ;
function ThunkActionCreator(text) {
return async function addTodoThunk(dispatch,getState){
const state = getState();
if(state.todo.length< TODO_MAX_COUNT){
dispatch(addTodoActionCreator('adding new thing to do... '));
setTimeout(()=>{
dispatch(removeTodoActionCreator());
dispatch(addTodoActionCreator(text));},3000);
return;
}else {
dispatch(addTodoActionCreator('no more than 3 things a day plz !'));
setTimeout(()=>{
dispatch(removeTodoActionCreator());
},3000);
}
}
}
export default ThunkActionCreator;
//container component (connect redux with react)
import { connect } from "react-redux";
import TodoApp from '../../components/TodoApp';
import { addTodoActionCreator, removeTodoActionCreator,removeAllActionCreator } from "../actions";
//import { addTodoActionCreator, removeTodoActionCreator,removeAllActionCreator } from "../ducks/todoDucks";
import ThunkActionCreator from '../thunks/addTodoThunk';
function mapStateToProps(state,ownProps){
return {todoItems:state.todo};
}
function mapDispatchToProps(dispatch,ownProps){
return {
addTodo: (text) =>{
//dispatch(addTodoActionCreator());
dispatch(ThunkActionCreator(text));
},
removeTodo: ()=>{
dispatch(removeTodoActionCreator());
},
removeAll: ()=>{
dispatch(removeAllActionCreator());
},
//dispatch async function (will handle in asyncFunctionMiddleware)
triggerAsyncFunction: (asyncFunction)=>{
dispatch(asyncFunction);
}
}
}
const TodoAppContainer = connect
(mapStateToProps, mapDispatchToProps)(TodoApp);
export default TodoAppContainer;
Thunk의 사용의 다양한 예시
1. Dispatching Action: Redux의 action들을 순서대로 dispatch해야 하는 상황
2. State의 값에 따른 조건부 dispatch
3. Action dispatch 이후에 state에 접근해야 하는 상황
4. cross-slice state 문제해결
5. 비동기와 side effect
6. Thunk에서 값을 반환 => 원하는 값을 반환시킬 수 있다.
데이터의 저장과 관련한 추가 설명
1.Store에 대한 추가 설명 :
redux 스토어에 데이터는 메모리에 올라가기 때문에 웹브라우저를
새로고침, 컴퓨터 재부팅 시에 redux store에 담겨있는 데이터들은 모두 날아간다.
이를 보완하기 위해 만들어진 것이 persist 라이브러리이다.
2.web storage API
key/value가 한쌍을 이루어서 저장된다. 각각의 key는 고유하고 동일한 key의 value를 바꾸면 덮어씌워지게 된다.
1)localStorage:
접속한 각 도메인과 프로토콜에 대해서 각기 다른 storage 객체를 리턴한다.
2)sessionStorage:
접속한 각 도메인, 프로토콜, 세션에 대해서 각기 다른 storage를 리턴한다.
세션이란 사용자가 접속한 순간 부터 나갈 때 까지의 시간 흐름을 세션이라고 한다.
각 세션에 mapping된 스토리지 객체를 반환한다. 따라서 한 도메인에 여러 탭에서
접속할 경우 각 탭마다 각각 다른 storage를 가진다.
데이타는 세션 종료 시에 만료된다.
3)차이점:
데이터의 만료여부. 로컬스토리지는 데이터가 계속 유지되는 반면,
세션스토리지는 세션이 종료되면, 데이터가 만료된다.
4)로그인과 관련하여 어디에 저장하면 좋을까?
사용자편의성과 지속성 => 로컬 // 보안우선=>세션. 다음을 참고하여 읽어보자.
로컬 스토리지 (localStorage):영구적인 보관:
로컬 스토리지에 저장된 데이터는 브라우저를 닫아도 계속해서 유지됩니다. 따라서 사용자가 다시 사이트를 방문할 때에도 여전히 로그인 상태가 유지됩니다.
간단한 구현: 로컬 스토리지는 간단하게 사용할 수 있으며, 데이터를 읽고 쓰는 과정이 간단합니다.
세션 스토리지 (sessionStorage):임시 보관:
세션 스토리지에 저장된 데이터는 브라우저 세션이 유지되는 동안에만 유효합니다. 브라우저를 닫으면 세션 스토리지에 저장된 데이터가 사라집니다.
보안 향상: 세션 스토리지는 로컬 스토리지보다 데이터에 더 짧은 수명을 부여하므로, 잠재적인 보안 위험을 줄일 수 있습니다. 로그인 토큰 등 민감한 정보를 저장할 때, 짧은 수명을 가지는 세션 스토리지를 사용하면 보안을 강화할 수 있습니다.
어떤 것을 선택해야 할까요?
보안: 보안이 중요한 경우, 로그인 토큰과 같은 민감한 정보는 가능한 한 세션 스토리지에 저장하는 것이 좋습니다. 세션 스토리지의 데이터는 브라우저 세션이 끝날 때 자동으로 삭제되기 때문입니다.
지속성: 사용자의 로그인 상태를 오랫동안 유지하려는 경우에는 로컬 스토리지를 고려할 수 있습니다.
데이터의 저장과 관련된 추가 설명
직렬화 (Serialize):
데이터는 key와 value 가 한 쌍을 이뤄서 storage의 저장되거나 저장되기 위해 전송된다.
그런데 이때 value는 값으로 문자열만 넣을 수 있다. 자바스크립트의 객체를 직렬화된 문자열로 변화시켜주는 대표적인 예가 JSON.stirigify()이다.
역직렬화는 JSON.parse()이며 문자열에서 다시 자바스크립트 객체로 만들어준다.
persist에서는 이 원리를 이용하여 데이터를 복원해주는데 Deserialize가 사용되고 있다.
marshalling unmarshalling이라고 부를 때도 있다.