// action type
const ADD_DATA = 'dataChange/add'
const DELETE_DATA = 'dataDelete/delete'
// action creator
// 액션객체를 타입으로, 준비물은 payload로 가지고 행위를 할 것이다 정의, 화살표 함수
export const addData = (payload) => {
return {type: ADD_DATA, payload: payload}
}
export const deleteData = (payload) => {
return {type: DELETE_DATA, payload: payload}
}
// reducer
export default function DataReducer (state=[], action) {
// state에 초기값 설정 state=[]
switch (action.type) {
// 액션 타입을 case와 비교하면서 맞는 case로 실행
case ADD_DATA:
console.log(state, action, [...state, action.payload])
return [...state, action.payload]
case DELETE_DATA:
return [...state].filter(object => object.title !== action.payload)
//object가 object.title을 가지고 있는지 확인
default:
return state
}
}
rootReducer를 사용해서 리듀서의 묶음 생성
import { createStore } from "redux";
import { combineReducers } from "redux";
import counter from "../modules/counter";
const rootReducer = combineReducers({
counter,
});
const store = createStore(rootReducer);
export default store;
import { createSlice } from "@reduxjs/toolkit";
const ToolkitSlice = createSlice({
name: "dataChange",
initialState: [],
reducers: {
ADD_DATA: (state, action) => {
console.log(state, action, [...state, action.payload])
return [...state, action.payload]
},
DELETE_DATA: (state, action) => {
return [...state].filter((object => object.title !== action.payload))
}
}
})
(위 예시 코드에는 없음)
import {createReducer} from '@reduxjs/toolkit'
const initialState = {
loading: false,
data: [],
error: null,
};
const reducer = createReducer(initialState, {
// push() 방식
[getUsersStart]: (state) => {
state.push({ loading: true });
},
// return 방식
[getUsersSuccess]: (state, action) => ({...state, loading: false, data: action.payload });
,
[getUsersFail]: (state, action) => {
state.push({ loading: false, error: action.payload });
},
});
export default reducer;
import { configureStore } from '@reduxjs/toolkit';
import ToolkitSlice from './modules/module';
export const store = configureStore({
reducer: {
data: ToolkitSlice.reducer,
},
});
export default store;
미들웨어란 액션과 리듀서 사이의 중간자이다.
thunk는 리덕스를 사용하는 애플리케이션에서 비동기 작업을 처리하는 용도로 사용하며, 특정 작업을 나중에 하도록 미루기 위해 함수형태로 감싼 것을 이야기한다.
thunk를 사용하면 dispatch를 할 때 객체가 아닌 함수를 dispatch 할 수 있게 한다.
이 함수를 thunk 함수라고 한다.
dispatch(함수) → 함수실행 → 함수안에서 dispatch(객체)
useEffect(() => {
dispatch(getPostAysnc());
}, []);
const postData = useSelector((state) => state.Post.data);
getPostAysnc()를 디스패치 했고, useSelctor를 이용해서 state값을 요청했다.
createAsyncThunk api를 사용해서 thunk 함수를 생성한다.
export const getPostAysnc = createAsyncThunk(
// createAsyncThunk는 비동기 작업을 처리하는 액션을 만들어 준다.
"post/getPost",
//"액션밸류/액션크리에이터"
async (thunkAPI) => {
try {
const res = await axios.get(get 요청할 api주소);
return res.data;
} catch (error) {
return thunkAPI.rejectWithValue(error);
}
}
);
export const PostSlice = createSlice({
name: "postReducer",
initialState: [],
reducers: {},
extraReducers: (builder) => {
builder
.addCase(getPostAysnc.fulfilled, (state, action) => ({
...state,
data: action.payload,
}))
.addCase(pickPostAysnc.fulfilled, (state, action) => {
state.data = action.payload;
});
},
});
동기적인 액션은 reducer, 비동기적 액션은 extraReducer
컴포넌트에서 useSelector로 스토어에 정보 요청 ->
reducers 실행 ->
extraReducer 에서 reducers 작업 상태에 따라 pending, fulfilled, rejected로 구분해서 builder.addCase() 내용 실행 ->
이 값이 state로 전달