LoginSignup
3
2

More than 3 years have passed since last update.

Reactでのformの挙動とfetchの備忘録

Posted at

最近、Next.jsを勉強していたのですが、Reactのことを結構忘れていてこれはまずいとなったので、復習している中での備忘録になります。

今回は、formfetchについて。

APIはjsonplaceholderを使います。さまざまなでもデータを用意してくれていて便利です。https://jsonplaceholder.typicode.com/というURLに/posts/todos/usersなどをつけることで違ったデータを参照できます。

そこで今回は、formのinputに文字を入力することで、postsやtodosなどを指定してデータをとってくるようにしたいと思います。

完成形は以下の通りです。この場合はfetchするURLがhttps://jsonplaceholder.typicode.com/todosとなっています。

image.png

言葉で説明するよりもコードを見ていただいた方がわかりやすいと思うので、コードを載せます。

Home.tsx
import React, { useState, useRef } from "react";

const Home: React.FC = () => {
  const [data, setData] = useState([]);
  const [text, setText] = useState("");
  const titleRef: any = useRef();

  const handlesubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();

    setText(titleRef.current.value);
    console.log(text);
    fetch(`https://jsonplaceholder.typicode.com/${text}`)
      .then((res) => {
        const data = res.json();
        return data;
      })
      .then((data) => setData(data));
  };

  return (
    <div>
      <form onSubmit={handlesubmit}>
        <input type="text" ref={titleRef} />
        <input type="submit" />
      </form>
      <div>
        <h2>ここにリスト表示</h2>
        <ul>
          {data.map((d: any) => (
            <li key={d.id} style={{ listStyle: "none" }}>
              {d.title}
            </li>
          ))}
        </ul>
      </div>
    </div>
  );
};

export default Home;

inputに入力される値のやりとりはuseRefを用いています。submitボタンを押すと、onSubmit={handlesubmit}が動いて、fetchなどを実行します。繰り返しになりますが、handlesubmitは以下の通りです。

Home.tsx
  const handlesubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();

    setText(titleRef.current.value);
    fetch(`https://jsonplaceholder.typicode.com/${text}`)
      .then((res) => {
        const data = res.json();
        return data;
      })
      .then((data) => setData(data));
  };

titleRef.current.valueとすることで、inputに入力された値を参照し、setText(titleRef.current.value)とすることで、その値をtextというstateに持たせることができます。

そしてfetchをします。URLのなかで、先ほどtextに持たせた値を展開することで、任意のデータを取得できるようにします。

fetchはPromiseを返す非同期処理なので、then()を使って処理していきます。res.json()はfetchして返されたデータをJSON形式にして解釈します。そのデータを格納したdataをそのままstateに持たせたいところですが、res.json()も非同期処理であるため、先にPromiseが返され、その後にデータが返されます。

なので、

Home.tsx
    fetch(`https://jsonplaceholder.typicode.com/${text}`)
      .then((res) => {
        const data = res.json();
        setData(data)
      })

このように記述すると、dataに何も入っていない状態になってしまうので、エラーになります。TypeScriptの場合はエディタで波線が引かれるはずです。ですので、setDataの部分もthenで繋ぐ必要があります。

さて、これで無事に取得したデータをdataというstateに持たせることができました。dataは配列なので、mapで回す必要があります。ですので、以下のようになりました。

Home.tsx
    <div>
      <form onSubmit={handlesubmit}>
        <input type="text" ref={titleRef} />
        <input type="submit" />
      </form>
      <div>
        <h2>ここにリスト表示</h2>
        <ul>
          {data.map((d: any) => (
            <li key={d.id} style={{ listStyle: "none" }}>
              {d.title}
            </li>
          ))}
        </ul>
      </div>
    </div>

本当はmapメソッドの引数(今回はd)の型はちゃんとつけたほうがいいのですが、今回は割愛します。

これで、formで入力したjsonplaceholderのURLからデータを取得し、表示することができました。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2