Study/Redux
redux_기본사용, 로거 미들웨어
Minhhk
2023. 10. 10. 21:01
ACTION : 간단한 js 객체..작업의 유형을 지정하는 'type 속성'이 있고, 선택적으로 redux 저장소에 일부 데이터를 보내는데 사용되는 'payload' 속성을 가질 수도 있다.
{type : 'members', memId : 2}
{type : 'USER_NAME', res : {id : 1, name : 'Kim'}}
{type : 'TEXT_LINE', text : '안녕하세요'}
REDUCER : 상태 변경 사항을 결정하고, 업데이트된 상태를 반환하는 함수. store 내부 상태를 업데이트 한다.
(prev, action) => nextState
STORE : 객체 저장소 _ 앱의 전체 상태 트리를 보유. 내부 상태를 변경하려면 Action을 전달해야 한다!
reducers 폴더를 만들어 사용할 reducer를 작성한다.
src/reducers/counter.tsx
interface Action {
type: string;
}
const counter = (state = 0, action: Action) => {
switch (action.type) {
case "INCREMENT":
return state + 1;
case "DECREMENT":
return state - 1;
default:
return state;
}
};
export default counter;
src/reducers/todos.tsx
enum ActionType {
ADD_TODO = "ADD_TODO",
DELETE_TODO = "DELETE_TODO",
}
interface Action {
type: ActionType;
text: string;
}
const todos = (state = [], action: Action) => {
switch (action.type) {
case "ADD_TODO":
return [...state, action.text];
default:
return state;
}
};
export default todos;
두 개의 reducer을 combineReducers 를 이용해 rootReducer 을 만든다.
src/reducers/index.ts
import { combineReducers } from "redux";
import counter from "./counter";
import todos from "./todos";
const rootReducer = combineReducers({
todos,
counter,
});
export default rootReducer;
export type RootState = ReturnType<typeof rootReducer>;
다음으로 store에 넣어준다.
const store = createStore(rootReducer);
그리고 <Provider >를 통해 store를 전달!!
<Provider store={store}>
<App/>
</Provider>
리듀서 등록 완료!
useSelector을 통해 store의 값을 꺼내 쓴다.
const todos = useSelector((state) => state.todos )
useDispatch() 를 통해 action을 전달 해준다.
dispatch({ type: "ADD_TODO", text: todoValue });
app.tsx
import { ChangeEvent, FormEvent, useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { RootState } from "./reducers";
type Props = {
value?: any;
onIncrement?: () => void;
onDecrement?: () => void;
};
function App({ value, onIncrement, onDecrement }: Props) {
const [todoValue, setTodoValue] = useState("");
// useSelector
const todos: string[] = useSelector((state: RootState) => state.todos);
const counter = useSelector((state: RootState) => state.counter);
// dispatch
const dispatch = useDispatch();
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
setTodoValue(e.target.value);
};
const addTodo = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
// dispatch
dispatch({ type: "ADD_TODO", text: todoValue });
setTodoValue("");
};
return (
<div>
<p>Clicked : {counter} times</p>
<button onClick={onIncrement}>+</button>
<button onClick={onDecrement}>-</button>
<ul>
{todos.map((todo, i) => (
<li key={i}>{todo}</li>
))}
</ul>
<form onSubmit={addTodo}>
<input type="text" value={todoValue} onChange={handleChange} />
<input type="submit" />
</form>
</div>
);
}
export default App;
index.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { applyMiddleware, createStore } from "redux";
import rootReducer from "./reducers";
import { Provider } from "react-redux";
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
);
// logger middleware_
const loggerMiddleware = (store: any) => (next: any) => (action: any) => {
console.log("store", store);
console.log("action", action);
next(action);
};
const middleware = applyMiddleware(loggerMiddleware);
const store = createStore(rootReducer, middleware);
const render = () =>
root.render(
<React.StrictMode>
<Provider store={store}>
<App
value={store.getState()}
onIncrement={() => store.dispatch({ type: "INCREMENT" })}
onDecrement={() => store.dispatch({ type: "DECREMENT" })}
/>
</Provider>
</React.StrictMode>
);
render();
store.subscribe(render);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
로거 미들웨어
dispatch에 의해 action이 작동 될 때, store & action의 로그를 볼 수있다.
// logger middleware_
const loggerMiddleware = (store: any) => (next: any) => (action: any) => {
console.log("store", store);
console.log("action", action);
next(action);
};
const middleware = applyMiddleware(loggerMiddleware);
const store = createStore(rootReducer, middleware);