ReactでのコンポーネントライフサイクルのuseEffectフックへの置き換え
序章
React Hooksは、Reactでの開発方法に革命をもたらし、最大の懸念事項のいくつかを解決しています。 The useEffect
フックを使用すると、反復的なコンポーネントのライフサイクルコードを置き換えることができます。
基本的に、フックはReact機能に「フック」できる特別な機能です。 以前に機能コンポーネントを作成し、それに状態を追加する必要があることに気付いた場合、フックは優れたソリューションです。
Hooksを初めて使用し、概要を知りたい場合は、 ReactHooksの概要を確認してください。
この記事は、あなたが useState
針。 そうでない場合は、恐れることはありません! Reactクラスベースのコンポーネントをステートフックを使用して機能的なコンポーネントに変換するのに少し時間を費やすと、正しい方向に進むことができます。
useEffectについて
useEffect
「副作用を使用する」の略です。 効果は、APIを操作するように、アプリケーションが外界と反応するときです。 これにより、何かが変更されたかどうかに基づいて関数を実行できます。 useEffect
また、組み合わせることができます componentDidMount
と componentDidUpdate
.
私たちのアプリについて
事前に作成されたクラスベースのコードを取得して、それを機能コンポーネントに変換します。 reactstrap を使用してフォーマットを簡素化し、axiosを使用して外部ダミーAPIを呼び出します。
具体的には、 jsonplaceholder を使用して、最初のコンポーネントマウントにダミーのユーザーデータを取り込みます。
次に、ユーザーのクリックに基づいてコンポーネントを再レンダリングし、ユーザーに関する追加データを取得します。
入門
開始コードを使用してリポジトリを複製するだけです。
$ git clone https://github.com/alligatorio/use-effect-hook
$ npm i
$ npm start
コード、特にコードに慣れるために少し時間を取ってください ClassBasedComponent.js
ファイル。
このファイルには2つのライフサイクルメソッドがあることに気付くでしょう。 componentDidMount
と componentDidUpdate
.
async componentDidMount() {
const response = await axios
.get(`https://jsonplaceholder.typicode.com/users`);
this.setState({ users: response.data });
};
async componentDidUpdate(prevProps) {
if (prevProps.resource !== this.props.resource) {
const response = await axios
.get(`https://jsonplaceholder.typicode.com/users`);
this.setState({ users: response.data });
}
};
これらは両方です async
jsonplaceholderAPIを呼び出してユーザーのリストを取り込むライフサイクルメソッド。
の componentDidMount
、最初のレンダリングでと言い、ユーザーデータを取得します。 次へ componentDidUpdate
何かが変わったかどうかを確認します props
. これは、この例のように、ボタンを押すなど、ユーザーが開始したイベントからトリガーできます。 変更が検出されたら、外に出てデータを再度取得します。
ライフサイクルメソッドを凝縮したいと思います useEffect
関数ベースのコンポーネントをフックして作成します。
コンポーネントを作成する
同じものを使用するのではなく ClassBasedComponent.js
ファイル、という新しいファイルを作成します FunctionBasedComponent.js
. 2つを対比して比較できるように、新しいファイルを作成しています。
ターミナルで、次のコマンドを実行して、ルートディレクトリから新しいファイルを作成できます。
$ touch FunctionBasedComponent.js
開始するには、以下のコードをコピーして新しいファイルに貼り付けてください。
import React, { useState, useEffect } from 'react';
import { Container, Button, Row } from 'reactstrap';
import axios from 'axios';
const FunctionBasedComponent = () => {
return (
<Container className="user-list">
<h1>My Contacts:</h1>
</Container>
)
};
export default FunctionBasedComponent;
今、あなたに飛び乗ってください App.js
ファイル、インポート FunctionBasedComponent.js
ファイルして置き換えます ClassBasedComponent
と FunctionBasedComponent
.
これで、アプリは次のスクリーンショットのようになります。
状態を初期化することから始めましょう useState
.
const [ users, setUsers ] = useState([]);
const [ showDetails, setShowDetails ] = useState(false);
すばやく要約するには useState
、初期化する state
とともに useState
フック、変数と配列内の変数に対応する関数の両方を宣言してから、 useState()
変数を初期化する引数。
- The
users
状態変数は空の配列で初期化され、次の関数が与えられます。setUsers
. - The
showDetails
状態変数は、の値で初期化されますfalse
との機能を割り当てましたsetShowDetails
.
API呼び出しを追加する
先に進んで、API呼び出しをとして追加しましょう fetchUsers
関数。
const fetchUsers = async () => {
const response = await axios.get(`https://jsonplaceholder.typicode.com/users`);
setUsers(response.data);
};
私たちは本質的にこれを引っ張っています async
前者からの電話 componentDidMount
と componentDidUpdate
機能。
使用できないことに注意してください async
内部で直接機能する useEffect
. 非同期関数を呼び出したい場合は、外部で関数を定義する必要があります useEffect
内でそれを呼び出します useEffect
.
useEffect引数
について話しましょう useEffect
ちょっとフックします。 のように componentDidMount
, useEffect
すぐに関数を呼び出します。
useEffect( () => {}, [ 'value' ]);
デフォルトでは、 useEffect
配列の値が異なるかどうかを確認し、異なる場合は、矢印関数が自動的に呼び出されます。
useEffect( () => {}, [ 'different value' ]);
コードエディタに戻って、 useEffect
呼び出す最新の関数の下にフックします fetchUsers
.
以下のコードでは、usersオブジェクトを調べて、変更があるかどうかを確認しています。
useEffect( () => { fetchUsers(users) }, [ users ] );
一般的な問題
- 配列をuseEffectフックに渡さないと、コンポーネントは継続的に繰り返しリロードされます。
useEffect( () => { fetchUsers(users) } );
- 空の配列を渡すと、変数は監視されないため、最初のレンダリングでのみ状態が更新されます。
componentDidMount
.
useEffect( () => { fetchUsers(users) }, [] );
- JavaScriptでオブジェクトを作成するたびに、それはメモリ内の異なるオブジェクトになります。 以下のコードはは同じように見えますが、各オブジェクトが異なるメモリアドレスに格納されているため、ページが再レンダリングされます。 同じロジックがアレイにも当てはまります。
useEffect( () => { fetchUsers(users) }, [{ user: 'Alli Alligator' }] );
等しくない!
useEffect( () => { fetchUsers(users) }, [{ user: 'Alli Alligator' }] );
useEffect
関数はクリーンアップ関数を返すか、何も返さない必要があります。
別の再レンダリングのトリガーを示すために、以下のコードをコピーして、 FunctionBasedComponent.js
ファイル:
import React, { useState, useEffect } from 'react';
import { Container, Button, Row } from 'reactstrap';
import axios from 'axios';
const FunctionBasedComponent = () => {
const [ users, setUsers ] = useState([]);
const [ showDetails, setShowDetails ] = useState(false);
const fetchUsers = async () => {
const response = await axios.get(`https://jsonplaceholder.typicode.com/users`);
setUsers(response.data);
};
useEffect( () => { fetchUsers(users) }, [ users ] );
const handleClick = event => { setShowDetails(!showDetails) };
return (
<Container>
{
users.map((user) => (
<ul key={ user.id }>
<li>
<strong>{ user.name }</strong>
<div>
<Button
onClick={ handleClick }
>
{ showDetails ? "Close Additional Info" : "More Info" }
</Button>
{ showDetails &&
<Container className="additional-info">
<Row>
{ `Email: ${ user.email }` }
</Row>
<Row>
{ `Phone: ${ user.phone }` }
</Row>
<Row>
{ `Website: ${ user.website }` }
</Row>
</Container>
}
</div>
</li>
</ul>
))
}
</Container>
)
}
export default FunctionBasedComponent;
今、私たちは onClick
ボタン内のイベント。 ボタンクリックで、の状態 showDetails
が変更され、APIを再度呼び出して、必要な追加の詳細を取り込む再レンダリングがトリガーされます。
Voilà!
async componentDidMount() {
const response = await axios.get(`https://jsonplaceholder.typicode.com/users`)
this.setState({ users: response.data })
};
async componentDidUpdate(prevProps) {
if (prevProps.resource !== this.props.resource) {
const response = await axios.get(`https://jsonplaceholder.typicode.com/users`)
this.setState({ users: response.data })
}
};
になる:
const fetchUsers = async () => {
const response = await axios.get(`https://jsonplaceholder.typicode.com/users`);
setUsers(response.data);
};
useEffect( () => { fetchUsers(users) }, [ users ] );