最近、Next.jsを勉強していたのですが、Reactのことを結構忘れていてこれはまずいとなったので、復習している中での備忘録になります。
今回は、form
とfetch
について。
APIはjsonplaceholderを使います。さまざまなでもデータを用意してくれていて便利です。https://jsonplaceholder.typicode.com/
というURLに/posts
や/todos
、/users
などをつけることで違ったデータを参照できます。
そこで今回は、formのinputに文字を入力することで、postsやtodosなどを指定してデータをとってくるようにしたいと思います。
完成形は以下の通りです。この場合はfetchするURLがhttps://jsonplaceholder.typicode.com/todos
となっています。
言葉で説明するよりもコードを見ていただいた方がわかりやすいと思うので、コードを載せます。
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
は以下の通りです。
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が返され
、その後にデータが返されます。
なので、
fetch(`https://jsonplaceholder.typicode.com/${text}`)
.then((res) => {
const data = res.json();
setData(data)
})
このように記述すると、dataに何も入っていない状態になってしまうので、エラーになります。TypeScriptの場合はエディタで波線が引かれるはずです。ですので、setData
の部分もthen
で繋ぐ必要があります。
さて、これで無事に取得したデータをdata
というstateに持たせることができました。dataは配列なので、map
で回す必要があります。ですので、以下のようになりました。
<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からデータを取得し、表示することができました。