FullStackOpen Part5-a Login in frontend メモ
Handling login
ログイン機能を付けたフロントエンド側のApp.jsはこんな感じ
const App = () => {
const [notes, setNotes] = useState([])
const [newNote, setNewNote] = useState('')
const [showAll, setShowAll] = useState(true)
const [errorMessage, setErrorMessage] = useState(null)
const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
useEffect(() => {
noteService
.getAll().then(initialNotes => {
setNotes(initialNotes)
})
}, [])
// ...
const handleLogin = (event) => {
event.preventDefault()
console.log('logging in with', username, password)
}
return (
<div>
<h1>Notes</h1>
<Notification message={errorMessage} />
<form onSubmit={handleLogin}>
<div>
username
<input
type="text"
value={username}
name="Username"
onChange={({ target }) => setUsername(target.value)}
/>
</div>
<div>
password
<input
type="password"
value={password}
name="Password"
onChange={({ target }) => setPassword(target.value)}
/>
</div>
<button type="submit">login</button>
</form>
// ...
</div>
)
}
export default App
<input>中のonChangeは関数自体を引数にとるので以下のようになる
eventオブジェクトからtargetを{}で直接取り出し、setUsernameにtarget.valueを収めている
onChange={({target}) => setUsername(target.value)}
以下のような感じでログイン済みかどうかでレンダリングする対象を変更
{user === null ?
loginForm() :
noteForm()
}
Creating new notes
ログインして取得したトークンを使用してノートを投稿できるようにする
import axios from 'axios'
const baseUrl = '/api/notes'
let token = null
const setToken = newToken => { token = `Bearer ${newToken}`}
const getAll = () => {
const request = axios.get(baseUrl)
return request.then(response => response.data)
}
const create = async newObject => {
const config = { headers: { Authorization: token }, }
const response = await axios.post(baseUrl, newObject, config) return response.data
}
const update = (id, newObject) => {
const request = axios.put(`${ baseUrl }/${id}`, newObject)
return request.then(response => response.data)
}
// eslint-disable-next-line import/no-anonymous-default-export
export default { getAll, create, update, setToken }
Saving the token to the browser's local storage
トークンをブラウザのストレージに保存しておくにはwindow.localStorageを使用する
W12のコンソールからもwindow.localStorageで見れる
以下使用例:
window.localStorage.setItem('name', 'juha tauriainen')
window.localStorage.getItem('name')
window.localStorage.removeItem('name')
オリジンごとにストレージは設定されている
ログインを変更すると以下のような感じに
const handleLogin = async (event) => {
event.preventDefault()
try {
const user = await loginService.login({
username, password,
})
window.localStorage.setItem('loggedNoteappUser', JSON.stringify(user))
noteService.setToken(user.token)
setUser(user)
setUsername('')
setPassword('')
} catch (exception) {
// ...
}
}
このままだとブラウザを更新するたびにログインしないといけないため、useEffectを使用し、コンポーネントが初回にレンダーされるときにlocalStrogeを確認するように設定
const App = () => {
const [notes, setNotes] = useState([])
const [newNote, setNewNote] = useState('')
const [showAll, setShowAll] = useState(true)
const [errorMessage, setErrorMessage] = useState(null)
const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
const [user, setUser] = useState(null)
useEffect(() => {
noteService
.getAll().then(initialNotes => {
setNotes(initialNotes)
})
}, [])
useEffect(() => {
const loggedUserJason = window.localStorage.getItem('loggedNoteappUser')
if (loggedUserJason) {
const user = JSON.parse(loggedUserJason)
setUser(user)
noteService.setToken(user.token)
}
}, [])
//....