npm i react-redux next-redux-wrapper @reduxjs/toolkit
npm i -D @types/react-redux typescript
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
export interface User {
id: number;
name: string;
}
//slice 안에 들어갈 내용은 name, init, reducers
//리덕스는 root reducer 객체를 가지고 있는데 이 객체의 key/ value쌍을 slice 라고 한다 요걸 업데이트 하는 reducer 함수가 slice reducer
//immer
export const usersSlice = createSlice({
name: 'users',
initialState: [
{ id: 1, name: '은지' }
] as User[],
//reducer 안에 여러가지 함수가 들어갈 수 있음. 더하기 빼기 등등.. 그때마다 name 바꿔줄 필요 없음
reducers: {
//액션타입은 슬라이스 이름을 접두어로 사용해서 자동 생성 >> 나같은 경우엔 users/addTodo
addUser: (state, action: PayloadAction<User>) => {
const { id, name } = action.payload;
state.push({ id, name });
// state.push(action.payload);
},
},
});
//위에 작성이 끝났다면 액션과 리듀서를 export 해준다.
// export const { addUser } = users.actions;
// export default users.reducer;
const { actions, reducer } = usersSlice;
export const { addUser } = actions;
export default reducer;
module/store.ts
import { configureStore } from '@reduxjs/toolkit';
import usersReducer from './slices/users';
const store = configureStore({
reducer: {
users: usersReducer,
},
});
export default store;
export type RootState = ReturnType<typeof store.getState>;
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import store from './modules/store';
import { BrowserRouter } from 'react-router-dom';
import Routes from './containers/web/routes';
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<BrowserRouter>
<Routes />
</BrowserRouter>
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
import { useState, ChangeEvent, FormEvent } from 'react';
import Modal from '~/containers/web/components/modal';
import { RootState } from '~/modules/store';
import { User, addUser } from '~/modules/slices/users';
import { Wrap } from './styled';
import { useDispatch, useSelector } from 'react-redux';
function Mypage() {
const [isOpen, setOpen] = useState(false);
const [name, setName] = useState('');
const users = useSelector<RootState, User[]>(state => state.users);
const dispatch = useDispatch();
function handle() {
setOpen(prev => !prev);
}
function handleChange(e: ChangeEvent<HTMLInputElement>) {
setName(e.currentTarget.value);
}
function handleSubmit(e: FormEvent) {
e.preventDefault();
dispatch(addUser({ name } as User));
setName('');
}
return (
<>
<p onClick={handle}>모달을 열어보자</p>
{isOpen && (
<Modal
type="alert"
handle={handle}
title={<h1>잠깐만~</h1>}
>
<Wrap>
<p>
자유롭게 모달 내용을 작성한다
</p>
</Wrap>
</Modal>
)}
<div>
<form onSubmit={handleSubmit}>
<input value={name} onChange={handleChange} />
<button>추가</button>
</form>
{users.map((u: any) => (
<div key={u.id}>{u.name}</div>
))}
</div>
</>
);
}
export default Mypage;