けど、そんな中で悩むことは、
・React HooksのuseEffectの第2引数で制御する方法がわからならい
ですよね。
今回はそんなお悩みを解決する
・React HooksのuseEffectの第2引数で制御する方法
についてまとめます!
もくじ
React HooksのuseEffectのとは
useEffectは、React Hooksの関数コンポーネントで、関数をマウントやレンダリング後のタイミングに応じて実行することができます。
具体的な処理内容はDOMへの入出力、オブジェクトやプロパティの代入や配列操作、外部APIとのデータ処理などとなっています。
Reactではこれらの処理を副作用と呼んでいて、副作用をきっかけに、関数として渡された処理を実行します。
React HooksのuseEffectの使い方
React HooksのuseEffectの使い方について説明をします。
React HooksのuseEffectの構文と引数
React HooksのuseEffectの構文と引数は以下の通りです。
React HooksのuseEffectの構文
useEffect(<第1引数>[, <第2引数>]);
React HooksのuseEffectの引数
第1引数 | マウントやレンダリング後に実行させたい副作用関数を指定します。 |
第2引数 | 副作用関数の実行タイミングを制御する依存データを指定します。 空の配列を記載した場合は初回レンダリング後のみ、何も記載しない場合は毎回のマウントやレンダリング後に実行されます。 |
React HooksのuseEffectを実装する
React HooksのuseEffectを実装するにはuseEffectをimportします。
import { useEffect, useState } from "react"
React HooksのuseEffectで登録がされたタイミングで実行する
まずは、React HooksのuseEffectで以下のTodoを入力し登録処理がされたタイミングで実行するよう設定をしていきましょう。
以下サンプルコードです。
import { useEffect, useState } from "react"
import { useForm } from "react-hook-form";
import { collection, getDocs, addDoc } from "firebase/firestore";
import fireStoreDB from "./firebase";
function App() {
//react-hook-form 初期設定
const { register, handleSubmit, formState: { errors } } = useForm();
//useState 初期設定
const [post, setPosts] = useState("まだ登録処理はされていません");
const [todos, setTodos] = useState([]);
//データ取得用配列
const arrList = [];
//FireStoreの登録-ここから
const fireStoreSubmit = async (data) => {
const { title, status, shousai } = data;
await addDoc(collection(fireStoreDB, "todoposts"), {
title: title,
status: status,
shousai: shousai,
});
console.log(title, status, shousai);
setPosts("登録処理がされました");
};
//FireStoreの登録-ここまで
//useEffectの処理-ここから
useEffect(() => {
console.log("useEffectが呼ばれました")
console.log(post);
const fireStorePostData = collection(fireStoreDB, "todoposts");
getDocs(fireStorePostData).then((snapShot) => {
snapShot.forEach((docs) => {
const doc = docs.data();
arrList.push({ id: docs.id ,title: doc.title ,status: doc.status, shousai: doc.shousai})
})
setTodos(arrList);
});
},[post]);
//useEffectの処理-ここまで
return (
<div>
<div>
<div>
<form onSubmit={handleSubmit(fireStoreSubmit)}>
<label>タイトル:</label><br/>
<input {...register("title", { required: true })} name="title" /><br/>
{errors.title && <p>必須です。タイトルを入力してください。</p>}
<label>ステータス:</label><br/>
<select {...register("status", { required: true })} name="status">
<option value=''>↓ステータス選択</option>
<option value='未着手'>未着手</option>
<option value='作業中'>作業中</option>
<option value='完了'>完了</option>
</select>
{errors.status && <p>必須です。ステータスを選択してください。</p>}<br/>
<label>詳細:</label><br/>
<textarea {...register("shousai", { maxLength: 10 })} name="shousai"/>
{errors.shousai && <p>10文字以内で入力してください。</p>}
<br/><input type="submit" value="登録" />
</form>
</div>
</div>
<ul>
{todos.map((todo) => (
<li key={todo.id}>
<div>タイトル:{todo.title}</div>
<div>ステータス:{todo.status}</div>
<div>詳細:{todo.shousai}</div>
</li>
))}
</ul>
</div>
);
}
export default App;
Todoの入力フォームに値を入力し、登録するとデータベースのFireStoreへ値が登録され、その値を再取得し、画面上に表示させる処理内容となっています。
Todo入力フォームとその下にデータベース登録済みのリストが表示されます。
Todoの入力フォームに値を入力し、登録すると
データベースのFireStoreへ値が登録されます。
FireStoreのデータを再取得し、画面上に表示させます。
初回表示は必ず1回useEffectが呼び出される
初回表示は必ず1回useEffectが呼び出されます。
コードを実装後、ブラウザを立ち上げ、コンソールを確認すると初回メッセージが出力されることがわかります。
登録処理を行いuseEffectの実行タイミングを確認する
useEffectの実行タイミングを確認していきましょう。
値を入力し、登録ボタンを押して実行します。
はい、登録後にuseEffectが実行されたことがわかりますね。
データベースのFireStoreへ値が登録され、
画面上に登録した値がリスト表示されました。
コードの説明
useEffectの第二引数の関数に変数「post」を指定し、変数「post」が変化されるタイミングのみ実行するよう設定をしています。
useEffect(() => {
…
});
},[post]);
変数「post」は登録処理後にsetPostsメソッドを通じて値を代入するようにしています。
const fireStoreSubmit = async (data) => {
…
setPosts("登録処理がされました");
};
React HooksのuseEffectで一度だけ処理をおこなう
React HooksのuseEffectで一度だけ処理をおこなう方法について説明をします。
同じくTodoのサンプルコードを使います。
import { useEffect, useState } from "react"
import { useForm } from "react-hook-form";
import { collection, getDocs, addDoc } from "firebase/firestore";
import fireStoreDB from "./firebase";
function App() {
//react-hook-form 初期設定
const { register, handleSubmit, formState: { errors } } = useForm();
//useState 初期設定
const [post, setPosts] = useState("まだ登録処理はされていません");
const [todos, setTodos] = useState([]);
//データ取得用配列
const arrList = [];
//FireStoreの登録-ここから
const fireStoreSubmit = async (data) => {
const { title, status, shousai } = data;
await addDoc(collection(fireStoreDB, "todoposts"), {
title: title,
status: status,
shousai: shousai,
});
console.log(title, status, shousai);
setPosts("登録処理がされました");
};
//FireStoreの登録-ここまで
//useEffectの処理-ここから
useEffect(() => {
console.log("useEffectが呼ばれました")
console.log(post);
const fireStorePostData = collection(fireStoreDB, "todoposts");
getDocs(fireStorePostData).then((snapShot) => {
snapShot.forEach((docs) => {
const doc = docs.data();
arrList.push({ id: docs.id ,title: doc.title ,status: doc.status, shousai: doc.shousai})
})
setTodos(arrList);
});
},[]);
//useEffectの処理-ここまで
return (
<div>
<div>
<div>
<form onSubmit={handleSubmit(fireStoreSubmit)}>
<label>タイトル:</label><br/>
<input {...register("title", { required: true })} name="title" /><br/>
{errors.title && <p>必須です。タイトルを入力してください。</p>}
<label>ステータス:</label><br/>
<select {...register("status", { required: true })} name="status">
<option value=''>↓ステータス選択</option>
<option value='未着手'>未着手</option>
<option value='作業中'>作業中</option>
<option value='完了'>完了</option>
</select>
{errors.status && <p>必須です。ステータスを選択してください。</p>}<br/>
<label>詳細:</label><br/>
<textarea {...register("shousai", { maxLength: 10 })} name="shousai"/>
{errors.shousai && <p>10文字以内で入力してください。</p>}
<br/><input type="submit" value="登録" />
</form>
</div>
</div>
<ul>
{todos.map((todo) => (
<li key={todo.id}>
<div>タイトル:{todo.title}</div>
<div>ステータス:{todo.status}</div>
<div>詳細:{todo.shousai}</div>
</li>
))}
</ul>
</div>
);
}
export default App;
一度だけ処理を行わせる場合はuseEffectの第二引数を「[]」に設定します。
useEffect(() => {
…
});
},[]);
初回表示は必ず1回useEffectが呼び出される
初回表示は必ず1回useEffectが呼び出されます。
登録処理を行いuseEffectの実行タイミングを確認する
useEffectの実行タイミングを確認していきましょう。
値を入力し、登録ボタンを押して実行します。
前回は登録後にuseEffectが実行されましたが、今回は実行されませんね。
ただ、useEffectではないsubmit処理は行われているので、
データベースのFireStoreへ値が登録されています。
useEffect内に記載されているデータの再取得処理は行われていないので、
画面上にのリストは変わらない結果となります。
1度だけ実行されるはずが2回実行されてしまう場合
useEffectの設定で1度だけ実行されるはずが2回実行されてしまう場合は、バグを踏んでいる可能性がありますので、
以下の記事にて確認をしてみてください。
React HooksのuseEffectで画面上の処理が行われる都度で処理をおこなう
React HooksのuseEffectで画面上の処理が行われる都度で処理をおこなう方法について説明をします。
同じくTodoのサンプルコードを使います。
import { useEffect, useState } from "react"
import { useForm } from "react-hook-form";
import { collection, getDocs, addDoc } from "firebase/firestore";
import fireStoreDB from "./firebase";
function App() {
//react-hook-form 初期設定
const { register, handleSubmit, formState: { errors } } = useForm();
//useState 初期設定
const [post, setPosts] = useState("まだ登録処理はされていません");
const [todos, setTodos] = useState([]);
//データ取得用配列
const arrList = [];
//FireStoreの登録-ここから
const fireStoreSubmit = async (data) => {
const { title, status, shousai } = data;
await addDoc(collection(fireStoreDB, "todoposts"), {
title: title,
status: status,
shousai: shousai,
});
console.log(title, status, shousai);
setPosts("登録処理がされました");
};
//FireStoreの登録-ここまで
//useEffectの処理-ここから
useEffect(() => {
console.log("useEffectが呼ばれました")
console.log(post);
const fireStorePostData = collection(fireStoreDB, "todoposts");
getDocs(fireStorePostData).then((snapShot) => {
snapShot.forEach((docs) => {
const doc = docs.data();
arrList.push({ id: docs.id ,title: doc.title ,status: doc.status, shousai: doc.shousai})
})
//setTodos(arrList);
});
},);
//useEffectの処理-ここまで
return (
<div>
<div>
<div>
<form onSubmit={handleSubmit(fireStoreSubmit)}>
<label>タイトル:</label><br/>
<input {...register("title", { required: true })} name="title" /><br/>
{errors.title && <p>必須です。タイトルを入力してください。</p>}
<label>ステータス:</label><br/>
<select {...register("status", { required: true })} name="status">
<option value=''>↓ステータス選択</option>
<option value='未着手'>未着手</option>
<option value='作業中'>作業中</option>
<option value='完了'>完了</option>
</select>
{errors.status && <p>必須です。ステータスを選択してください。</p>}<br/>
<label>詳細:</label><br/>
<textarea {...register("shousai", { maxLength: 10 })} name="shousai"/>
{errors.shousai && <p>10文字以内で入力してください。</p>}
<br/><input type="submit" value="登録" />
</form>
</div>
</div>
<ul>
{todos.map((todo) => (
<li key={todo.id}>
<div>タイトル:{todo.title}</div>
<div>ステータス:{todo.status}</div>
<div>詳細:{todo.shousai}</div>
</li>
))}
</ul>
</div>
);
}
export default App;
随時処理を行わせる場合はuseEffectの第二引数を空に設定します。
useEffect(() => {
…
});
},);
またuseEffectの中にある処理はいったん無効化します。
//setTodos(arrList);
初回表示は必ず1回useEffectが呼び出される
初回表示は必ず1回useEffectが呼び出されます。
登録処理を行いuseEffectの実行タイミングを確認する
useEffectの実行タイミングを確認していきましょう。
値を入力しないで、登録ボタンを押して実行します。
react-hook-formコンポーネントによるエラーチェック処理が実行され、
そのタイミングでuseEffectが実行されることがわかりますね。
さいごに
いかがでしょうか。
今回は、
・React HooksのuseEffectの第2引数で制御する方法
についてまとめました。
また、他にも便利な方法がありますので、よろしければご参照頂ければと思います。