Redux 실습 코드 - Redux를 이용한 로그인, 로그아웃 예제
따로 파일을 만들어서 실습해보고 공부한 내용들 전부 긁어놓은 리액트 실습 페이지에다가 넣는 것까지 해보자
로그인 하기 전과 로그인 하고 난 후의 화면을 보여줄 컴포넌트
프로필 페이지에서 사용자 정보를 보여준다. 결론적으로는 스토어에 저장해놓은 State(데이터)들을 가져와서 여기다 뿌리는 것이다.
import React from 'react';
import { useSelector } from 'react-redux';
function Profile() {
const user = useSelector(state => state.user.value);
return (
<div>
<h1>Profile Page</h1>
<p> Name : {user.name}</p>
<p> Age : {user.age} </p>
<p> Email : {user.email}</p>
</div>
);
}
export default Profile;
useSelector 를 이용하면 만들어놓은 리듀서에 접근할 수 있다.
(순서가 좀 뒤죽박죽이긴 하지만..)
리듀서에 뭐 많이 정의해놓을 수 있다고 했다 => 객체형식으로 되어 있음
리듀서에 있는 state에 접근할건데, 어느 state냐 하면 ? 아까 user라고 이름 지어준 리듀서에 있는 state에 접근할거란 말
그리고 user 리듀서에가 value로 초기값을 설정해놨다. 제일 처음엔
state => state.user.value
그 초기값들로 세팅을 해놓는다.
Store를 식당으로 생각하면, 리듀서는 접시이다. 음식(데이터, 상태값)들을 줘야하는데 접시에 올려다 줄거다.
import React from 'react';
import { configureStore } from '@reduxjs/toolkit';
import userSlice from './User';
// 삭당에다가 접시 등록하기
export default configureStore({
reducer: {
user: userSlice,
},
});
리덕스는 스토어에 모든 state 상태값(데이터)을 저장한다. 공식문서에서는 app폴더에 만들던데 어디다 만들던 사실 상관없다.
index.js에 만드는 사람도 있더라 => 이건 좀..;
configureStore라는 키워드 (=> 식당)가 reducer를 감싸고 있다. 저기서 모든 state를 관리한다.
이제 이 스토어를 연결시켜줘야 하는데 보통의 경우에는 index.js 에다가 연결해준다.
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById('root')
나는 index.js에서 뭔가를 해주는 게 뭔지 모르게 좀.. 불편해서 그냥 App.js에서 해줬다.
import Profile from './Components/Profile';
import Login from './Components/Login';
import { Provider } from 'react-redux';
import Store from './Redux/Store';
function App() {
return (
<Provider store={Store}>
<div className="App">
<Profile />
<Login />
</div>
</Provider>
);
}
export default App;
그리고 Provider 키워드로 App 전체를 감싸줘야 한다.
Provider 는?
store가 리액트 앱 전체를 감싸도록 해주는 역할이다. 공식문서에는 "Provider 는 react-redux 라이브러리에 내장되어있는, 리액트 앱에 store 를 손쉽게 연동 할 수 있도록 도와주는 컴포넌트입니다. 이 컴포넌트를 불러온다음에, 연동할 컴포넌트를 감싸준다음에 Provider 컴포넌트의 props로 store 값을 설정해주면 됩니다." 라고 나와있다.
이제 "접시" 즉, 리듀서를 만들어준다.
import { createSlice } from '@reduxjs/toolkit';
const initialStateValue = { name: '이름 초기값', age: 0, email: '이메일 초기값' };
const userSlice = createSlice({
name: 'user',
initialState: { value: initialStateValue },
reducers: {
login: (state, action) => {
state.value = action.payload;
},
logout: state => {
state.value = initialStateValue;
},
},
});
export const { login, logout } = userSlice.actions;
export default userSlice.reducer;
액션 객체를 받으면 전달받은 액션의 타입에 따라 어떻게 상태를 업데이트 해야 할지 정의를 해줘야한다. 이 때 업데이트 로직을 정의하는 함수를 리듀서라고 부른다. 이 함수는 나중에 우리가 직접 구현하게 된다. => login
예를 들어 type 이 INCREMENT 라는 액션이 들어오면 숫자를 더해주고,
DECREMENT 라는 액션이 들어오면 숫자를 감소시키는 그런 작업을 여기서 하면 된다.
리듀서 함수는 두가지의 파라미터를 받는다.
state: 현재 상태, action: 액션 객체
그리고, 이 두가지 파라미터를 참조하여, << 새로운 상태 객체를 만들어서 >> 이를 반환한다.
여기서 createSlice 라는 메서드를 쓴다. createSlice 는 기존에 createReducer와 createAction 이 하던 일을 같이 해준다. 쉽게 말해 actions를 위한 js파일을 따로 만들 필요가 없게 되는 것이다.
사용할 리듀서의 이름을 정하고(user), 그걸 createSlice로 지정해준다.
name 은 리듀서 이름 뭘로 할지 정하기
initialState 는 들어갈 데이터의 초기값 세팅하는 용도
=> 로그아웃할 때도(초기화) 똑같이 쓰이니 변수로 만들어놓고 재활용
=> initialStateValue
reducers 는 상태가 변하면 어떻게 로직을 실행하면 될 지 정하는 부분
=> 우리는 로그인 버튼을 눌렀을때 이름, 나이, 이메일이 변하게 하고 싶으니
로그인 함수를 만들어준다. + 로그아웃
state는 우리가 잡아놓은 초기값의 value를 가져오는 역할을 하고, actions안에 payload랑 type 이 있는데 이는 우리가 바꾸고 싶은 데이터를 원하는 곳에다가 넘겨주는 역할을 한다.
순서가 좀 엉망이지만? 리듀서(접시)를 만들었으니 식당(스토어)에다가 등록하는 것이다.
=> Store.js
코드 제일 밑에 export 부분은
아까 만들어둔 login이라는 함수를 action 기능이 작동하도록 다른데서 쓸거라는 뜻이다.
=> "액션을 디스패치 하기 위함"
공식 문서에 나와있는 예제에서는 다음과 같다.
export const { increment, decrement, incrementByAmount } = counterSlice.actions
import React from 'react';
import { useDispatch } from 'react-redux';
import { login, logout } from '../Redux/User';
function Login() {
const dispatch = useDispatch();
// action 을 보내는 역할, 디스패치를 날리는 역할
return (
<div>
<button
onClick={() => {
dispatch(login({ name: '서지원', age: 25, email: 'zwon2056@gmail.com' }));
}}
>
Login
</button>
<button
onClick={() => {
dispatch(logout());
}}
>
Logout
</button>
</div>
);
}
export default Login;
useDispatch 훅을 사용한다.
=> action을 보내는 역할이다 ("디스패치를 날린다"라고도 한다)
onClick 이벤트로 콜백 함수를 호출하는데 그 때 dispatch 가 사용된다.
=> 버튼을 클릭할 때마다 디스패치를 날린다
=> login을 날린다
=> login은 User에서 "다른 곳에서도 action 으로 작동 할 수 있도록" 만들어놨다 (바로 위에 User.js 에서 export 부분에 해당)