Provider컴포넌트를 통해 앱의 다른 컴포넌트에서 Redux store를 사용할 수 있다
import { Provider } from 'react-redux'
import store from './store'
//index.js
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<Provider store={store}>
<App />
</Provider>
);
import { connect } from 'react-redux';
💡 argument로 state, dispatch를 가짐
state: Redux store에서 온 state
dispatch: component의 props
connect()는 return한 것을 component의 prop
에 추가해준다.
두 종류의 argument와 함께 호출되는 함수
function mapStateToProps(state, ownProps)
function mapStateToProps(state) {
return { toDos: state };
}
export default connect(mapStateToProps)(Home);
<ul>{JSON.stringify(toDos)}</ul>
→ toDos 상태
function mapDispatchToProps(dispatch) {
return {
addToDo: text => dispatch(actionCreators.addToDo(text))
};
}
-> component로부터 reducer에게 dispatch하기
function mapStateToProps(state) {
return { toDos: state };
}
function mapDispatchToProps(dispatch) {
return {
addToDo: text => dispatch(actionCreators.addToDo(text))
};
}
export default connect(mapStateToProps, mapDispatchToProps)(Home);
-> 컴포넌트가 직접 dispatch나 actionCreators 할 필요 없이 두개의 함수를 만든다
Redux store에서 dispatch 함수에 대한 참조를 반환
(mapDispatchToProps대신 사용 가능)
import { useDispatch } from 'react-redux'
const dispatch = useDispatch()
dispatch(addTodo(text));
const dispatch = useDispatch();
const onClick = () => {
dispatch(deleteTodo(id));
};
< button onClick={onClick} >❌< /button >
function ToDo({ text, onBtnClick }) {
return (
<li>
{text} <button onClick={onBtnClick}>DEL</button>
</li>
);
}
function mapDispatchToProps(dispatch, ownProps) {
return {
onBtnClick: () => dispatch(actionCreators.deleteToDo(ownProps.id)),
};
}
const dispatch = useDispatch();
const onClick = () => {
dispatch(deleteTodo(id));
};
< button onClick={onClick} >DEL< /button >
-> useDispatch를 사용하면 더 간단해진다
자바스크립트에서 지원하는 Optional Chaining 기능
function Detail({ toDos }) {
const myId = useParams().id;
const toDo = toDos.find((toDo) => toDo.id === parseInt(myId));
return (
<>
<h1>{toDo?.text}</h1>
<h5>Created at: {toDo?.id}</h5>
</>
);
}
props에 빈객체가 나와서 useParams사용했다
const myId = useParams().id;
const toDo = toDos.find((toDo) => toDo.id === parseInt(myId));
find()를 사용해 id가 같은 것 찾아냄
적은 양의 코드로 같은 기능 하기
Redux action type 및 creator를 정의하기 위한 helper 함수
import { createAction } from "@reduxjs/toolkit";
-> import
const ADD = "ADD";
const addToDo = text => {
return {
type: ADD,
text
};
};
이 코드를
const addToDo = createAction("ADD");
이렇게 줄일 수 있다 → 예전과 달리 action을 정의하지 않아도 됨
action은 type(string)과 payload를 갖는다
(내가 어떠한 정보를 보내든 payload와 함께 보내짐)
const reducer = (state = [], action) => {
switch (action.type) {
case addToDo.type:
return [{ text: action.payload, id: Date.now() }, ...state];
case deleteToDo.type:
return state.filter(toDo => toDo.id !== action.payload);
default:
return state;
}
};
이 코드를 → state를 mutate 하지 못함 → 새로운 state 생성
const reducer = createReducer([], {
[addToDo]: (state, action) => {
state.push({ text: action.payload, id: Date.now() });
},
[deleteToDo]: (state, action) =>
state.filter(toDo => toDo.id !== action.payload)
});
이렇게 줄일 수 있다 → state mutate 가능
store 설정에 몇몇 기본 값을 추가
- state를 볼 수 있다 (type, payload)
- 언제 어떤 action이 발생했는지 알 수 있다
- dispatcher 사용
const store = configureStore({ reducer });
reducer뿐만 아니라 action도 생성해줌
초기 state, reducer 함수의 객체, "slice 이름"을 받아 리듀서 및 state에 해당하는 action crator와 action type을 자동으로 생성하는 함수
const addToDo = createAction("ADD");
const deleteToDo = createAction("DELETE");
const reducer = createReducer([], {
[addToDo]: (state, action) => {
state.push({ text: action.payload, id: Date.now() });
},
[deleteToDo]: (state, action) =>
state.filter(toDo => toDo.id !== action.payload)
});
이 코드를
const toDos = createSlice({
name: "toDosReducer",
initialState: [],
reducers: {
add: (state, action) => {
state.push({ text: action.payload, id: Date.now() });
},
remove: (state, action) => state.filter(toDo => toDo.id !== action.payload)
}
});
요런식으로 줄여서 사용할 수 있다