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))
    })
}


この記事が気に入ったらサポートをしてみませんか?