FullStackOpen Part2-d Altering data in server メモ
REST
データごとにURLが用意され取得できる
Sending Data to the Server
addNoteイベントハンドラ中でaxios.postを実行
POSTしたデータは開発ツールのネットワークタブで確認可
const addNote = (event) => {
event.preventDefault()
const noteObject = {
content: newNote,
important: Math.random() < 0.5,
}
axios
.post('http://localhost:3001/notes', noteObject) //ここでポスト
.then(res => {
console.log(res)
setNotes(notes.concat(res.data)) //そのままでは画面が更新されないのでnotesを更新
setNewNote('') //newNoteを更新し、入力ボックスを空にする
})
}
Changing the Importance of Notes
note.importantを変えるコードは以下の通り
const url = `http://localhost:3001/notes/${id}` でNoteのインスタンスを指定
ドル括弧を使用するときは'シングルクォーテーションではなく`バッククォーテーションで囲む
idの対応するNoteを見つけるにはfindを使用する
importantだけ変更したnoteオブジェクトを作るときは {…note, }をうまく使う 直接noteオブジェクトを変更してはいけない(ステートであるため)
PUT関数を使用して更新する
画面表示を更新するためにsetNotesで更新
その際にmapで変更対象のみres.dataで表示するように変更
const toggleImportance = (id) => {
console.log('importance of', id, 'need to be changed')
const url = `http://localhost:3001/notes/${id}`
const note = notes.find(note => note.id === id)
const changedNote = { ...note, important: !note.important }
axios
.put(url, changedNote)
.then(res => {
setNotes(notes.map(note => note.id !== id ? note : res.data))
})
}
Extraction Communication with the Backend into a Separate module
すべてApp.jsに書くのはあれなのでnotes.jsというモジュールに分ける
import axios from "axios"
const baseUrl = 'http://localhost:3001/notes'
const getAll = () => {
const req = axios.get(baseUrl)
return req.then(res => res.data) //データだけ返すようにしている
}
const create = (newObject) => {
const req = axios.post(baseUrl, newObject)
return req.then(res => res.data)
}
const update = (id, newObject) => {
const req = axios.put(`${baseUrl}/${id}`, newObject)
return req.then(res => res.data)
}
export default {
getAll: getAll,
create: create,
update: update
}
getAllで返されるのはreqのthen。reqで返されるのもPromiseだが、req.thenもまたプロミス!そのためApp.js側では以下のようになる
const hook = () => {
noteService
.getAll()
.then(initialNote => {
setNotes(initialNote)
})
}
useEffect(hook, [])
getAll().then()とthenが連なる状態に。ただし受け取る引数はresではなくres.dataなのでそのままsetNotesに入れられるようになった。
req -> then(reqからresに) -> then(resからdataに) というながれ
Cleaner Syntax for Defining Object Literals
オブジェクト定義でキーと変数が同名の場合は以下のように省略可
export default { getAll, create, update}
Promises and Errors
Promiseがrejectedになるとアプリケーションではエラーが発生するが、ユーザーからすると何が起こったかわからない
そのような場合に備えてcatchを使う
axios.get(baseUrl).then(res => …).then(…).catch(error => console.log(error))
たとえば既に存在しないnoteのimportanceをトグルする場合、以下のようなcatchを入れておく
const toggleImportanceOf = id => {
const note = notes.find(n => n.id === id)
const changedNote = { ...note, important: !note.important }
noteService
.update(id, changedNote).then(returnedNote => {
setNotes(notes.map(note => note.id !== id ? note : returnedNote))
})
.catch(error => {
alert(
`the note '${note.content}' was already deleted from server`
)
setNotes(notes.filter(n => n.id !== id))
})
}