✅ Redux-toolkit 개요
✅ 여러가지 state 관리(로그인)
🚀 Redux toolkit 장점
- 우리는 react-redux라는 아주 고마운 존재가 있다고 저번 시간에 배웠지만, 이번엔 더 쉬운 놈을 들고 왔다. 바로 Redux toolkit이다.
- createSlice로 여러가지의 state를 쉽게 만들어 관리가 가능하다
- Slice에는 자동으로 state 객체를 복사해서 새로운 객체를 만든다. 그렇기 때문에 reducer함수로 직접 state 값을 변경을 해주더라도, 상관이 없다.
🚀 Redux toolkit에서 store 만들기
createSlice({ name : "counter", initialState , reducers:{ increment(state){state.counter++}, decrement(state){state.counter--}, increase(state,action){state.counter+action.amount}, toggleCounter(state){state.show=!state.show} } });
- 이전에 작성했던 카운터 함수를 이용했을 때보다 훨씬 짧아졌다. 우선 각각의 조건문을 모두 action으로 받아서 해당 action값일 때만 실행해주는 값이 달라야했던 때에 비해
- redux-toolkit의 활용으로 함수로 선언을 해주니 각각의 상태값으로 행위를 분리할 필요가 없이 다른 함수를 호출하면 된다.
- 그리고 redux에서 객체값을 복사하니 state값을 직접 바꿔주는 것처럼 작성해도 아무 문제가 없어지게 된다. magic!
🚀 Redux-toolkit에서 state호출하는 방법
const store = configureStore({ reducer : counterSlice.reducer }); const store = configureStore({ reducer : { counter: counterSlice.reducer, addCounter : addCounterSlice.reducer, } });
- slice를 만들었다면 store를 정의하고, 불러와야함.
- 이 때 사용하는 것이 configureStore임. configureStore의 가장 큰 장점은 여러 reducer를 한 번에 묶어서 관리가 가능하다는 것이다. 아래처럼 객체상태로 말이다.
🚀 Reducer 보내기
export const counterActions = counterSlice.actions;
import { counterActions } from "../store"; const incrementHandler = () => { dispatch(counterActions.increment()) } const increaseHandler = () => { dispatch(counterActions.increase(5)) }
- index.js의 store에서 진행하는 counterAction이라는 action을 전달하고 변수에 저장을 한다. 그럼 변수에는 각 reducer들이 자동으로 객체형태로 들어가게 된다.
- 인자 값은 payload로 전달이 된다.
이제는 login과 logout 상태를 관리해서 각 상태마다 다른 것들을 보여주고자 한다.
로그아웃시 페이지
로그인시 페이지
🚀 store 설계하기
const initialAuthState = { isAuthenticated: false } const authSlice = createSlice({ name : 'authentication', initialState: initialAuthState, reducers : { login(state){ state.isAuthenticated=true; }, logout(state){ state.isAuthenticated=false; } } }); export const authActions = authSlice.actions;
- 위와 같이 기본 값을 false로 가지고 있는 state를 만들어주고, slice를 생성한다. 해당 slice의 이름과 기본 state값 설정, reducer 함수를 만들어서 해당 state가 바뀔 때 마다 값을 변경해주는 store를 만들었다.
🚀 App.js에서 state 변경해주기
function App() { const isLogin = useSelector(state => state.auth.isAuthenticated) return ( <> <Header /> {/* {!isLogin && <Auth/>} {isLogin && <UserProfile/>} */} {isLogin === false ? <Auth /> : <UserProfile/>} <Counter /> </> ); }
- 우선 App.js에서 각 상태마다 보여지는 것이 다르기 때문에 설정을 해줘야함
- 삼항연산자를 사용할 수도 있고, &&를 이용해서 true를 충족시켰을 때 다른 페이지를 보여주는 형태로 작성해도 된다.
🚀Header.js에서 state 변경해주기
import { useDispatch, useSelector } from "react-redux"; import classes from './Header.module.css'; import { authActions } from "../store/auth"; const Header = () => { const dispatch = useDispatch() const isLogout = useSelector(state => state.auth.isAuthenticated) const handleLogout = () => { dispatch(authActions.logout()) } return ( <header className={classes.header}> <h1>Redux Auth</h1> <nav> { isLogout === false ? null : ( <ul> <li> <a href='/'>My Products</a> </li> <li> <a href='/'>My Sales</a> </li> <li> <button onClick={handleLogout}>Logout</button> </li> </ul> ) } </nav> </header> )
- 로그아웃 상태에서의 헤더의 특정 영역이 달라지기 때문에 위와 같이 header에서 설정해줘야한다.
🚀Auth.js에서 state 변경해주기
import { useDispatch, useSelector } from "react-redux"; import { authActions } from "../store/auth"; import classes from './Auth.module.css'; const Auth = () => { const dispatch = useDispatch() const isLogin = useSelector(state => state.auth.isAuthenticated) const handleLogin = () => { dispatch(authActions.login()) } return ( <main className={classes.auth}> <section> <form> <div className={classes.control}> <label htmlFor='email'>Email</label> <input type='email' id='email' /> </div> <div className={classes.control}> <label htmlFor='password'>Password</label> <input type='password' id='password' /> </div> <button onClick={handleLogin}>Login</button> </form> </section> </main> ); }; export default Auth;
- 이 때 login button에 handler를 줬는데. 그렇게 되면 데이터 전송이 form을 통해서 되지 않으니까 form을 통해 handler를 통제하는것이 맞다. 따라서 아래와 같이 변경해서 코드를 작성할 수 있도록 하자
- form을 다루는 방법을 아직 잘 모르니 추후 공부를 더 해볼 것!
🚀 form 수정
const Auth = () => { const dispatch = useDispatch() const isLogin = useSelector(state => state.auth.isAuthenticated) const handleLogin = (event) => { event.preventDefault(); dispatch(authActions.login()); } return ( <main className={classes.auth}> <section> <form onSubmit={handleLogin}> <div className={classes.control}> <label htmlFor='email'>Email</label> <input type='email' id='email' /> </div> <div className={classes.control}> <label htmlFor='password'>Password</label> <input type='password' id='password' /> </div> <button>Login</button> </form> </section> </main> ); }; export default Auth;