序章

React Hooksは、Reactでの開発方法に革命をもたらし、最大の懸念事項のいくつかを解決しています。 The useEffect フックを使用すると、反復的なコンポーネントのライフサイクルコードを置き換えることができます。

基本的に、フックはReact機能に「フック」できる特別な機能です。 以前に機能コンポーネントを作成し、それに状態を追加する必要があることに気付いた場合、フックは優れたソリューションです。

Hooksを初めて使用し、概要を知りたい場合は、 ReactHooksの概要を確認してください。

この記事は、あなたが useState 針。 そうでない場合は、恐れることはありません! Reactクラスベースのコンポーネントをステートフックを使用して機能的なコンポーネントに変換するのに少し時間を費やすと、正しい方向に進むことができます。

useEffectについて

useEffect 「副作用を使用する」の略です。 効果は、APIを操作するように、アプリケーションが外界と反応するときです。 これにより、何かが変更されたかどうかに基づいて関数を実行できます。 useEffect また、組み合わせることができます componentDidMountcomponentDidUpdate.

私たちのアプリについて

事前に作成されたクラスベースのコードを取得して、それを機能コンポーネントに変換します。 reactstrap を使用してフォーマットを簡素化し、axiosを使用して外部ダミーAPIを呼び出します。

具体的には、 jsonplaceholder を使用して、最初のコンポーネントマウントにダミーのユーザーデータを取り込みます。

次に、ユーザーのクリックに基づいてコンポーネントを再レンダリングし、ユーザーに関する追加データを取得します。

入門

開始コードを使用してリポジトリを複製するだけです。

$ git clone https://github.com/alligatorio/use-effect-hook
$ npm i
$ npm start

コード、特にコードに慣れるために少し時間を取ってください ClassBasedComponent.js ファイル。

このファイルには2つのライフサイクルメソッドがあることに気付くでしょう。 componentDidMountcomponentDidUpdate.

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 ファイルして置き換えます ClassBasedComponentFunctionBasedComponent.

これで、アプリは次のスクリーンショットのようになります。


状態を初期化することから始めましょう 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 前者からの電話 componentDidMountcomponentDidUpdate 機能。

使用できないことに注意してください 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 ] );