回到前端部分,在 api 中新增 login
及 register
createAsyncThunk
接著新增 accountSlice.js
login
及 register
,然後使用 createAsyncThunk
來處理非同步函數extraReducers
extraReducers
用來處理 createAsyncThunk
建立的非同步函數,可以分為三個階段:pending
, fulfilled
, rejected
,依照字面上的意思很好理解,我們可以分別定義在各自的階段需要執行什麼任務,例如 status
的狀態以及是否成功註冊或登入的 login.hasLogin
布林值判斷Login.js
及 Register.js
接下來調整登入及註冊頁面的功能:
loginAsync
,並在 handleLogin
中搭配 dispatch
使用useSelector
,取出全域變數 account.status
以及 account.user
,並使用 useEffect
來判斷 loginAsync
的執行階段useNavigate
,如果登入成功的話,將畫面跳轉至首頁 → navigate('/')
import React, { useState, useEffect } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';
import { EnvelopeIcon, LockClosedIcon } from '@heroicons/react/24/solid';
import Header from '../components/Header';
import Footer from '../components/Footer';
import { loginAsync } from '../redux/accountSlice';
export default function Login() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const navigate = useNavigate();
const loginStatus = useSelector((state) => state.account.status);
const user = useSelector((state) => state.account.user);
const dispatch = useDispatch();
const handleLogin = async () => {
dispatch(loginAsync({ email, password }));
};
useEffect(() => {
if (loginStatus === 'idle' && user.name) {
alert('登入成功!');
navigate('/');
}
}, [loginStatus]);
...
}
Register.js
也是相同的概念~
Header.js
取得全域變數 account.login.hasLogin
以及 account.user
,並使用 hasLogin
來判斷使用者是否已登入來改變 header 的顯示 → {hasLogin ? <></> : <></>}
import { useSelector } from 'react-redux';
const { hasLogin } = useSelector((state) => state.account.login);
const { name, photo } = useSelector((state) => state.account.user);
{hasLogin ? (
<>
<Link
to={'/add-post'}
className="flex mx-5 text-white font-medium px-4 py-2 bg-yellow-700/40 hover:bg-yellow-700/70 rounded-md"
>
<PencilIcon className="h-6 w-6 mr-2" />
寫點東西
</Link>
<Link to={'/'} className="flex mx-5 hover:text-yellow-700 align-middle">
{photo ? (
<img className="w-9 h-9 rounded-full" src={photo} alt="avatar" />
) : (
<div className="w-9 h-9 rounded-full bg-yellow-700/70" />
)}
<span className="font-medium ml-4 my-auto">Hi, {name}</span>
</Link>
</>
) : (
<Link
to={'/login'}
className="flex mx-5 text-white font-medium px-4 py-2 bg-yellow-700/40 hover:bg-yellow-700/70 rounded-md"
>
登入 / 註冊
</Link>
)}
AddPost.js
取得全域變數 account.user
中的 name
,然後傳給 createPost
api
import { useSelector } from 'react-redux';
const author = useSelector((state) => state.account.user.name);
const handleAddPost = async () => {
const res = await createPost({ title, author, image, content });
console.log(res.data);
setTitle('');
setImage('');
setContent('');
};
目前的畫面及功能呈現
這樣就大致完成了註冊 / 登入的功能啦~ 當然還有很多細節需要調整及修改,如果後續有機會再來調整!