カスタム反応呼び出しでハンドルAPI呼び出しプロセス


反応は人気のUIライブラリです.フックのデビューでは、今すぐ反応成分は非常にクリーナーであり、ロジックはより再利用可能です.
いくつかのAPIの呼び出しを実行し、状態を追跡しようとするときに反応する一般的なケースの一つです.

伝統的な方法


したがって、これはAPI呼び出しプロセスに対処する一般的で伝統的な方法です
import React, { useEffect, useState } from "react";

export const ListUser = () => {
  const [loading, setLoading] = useState(false);
  const [results, setResults] = useState([]);
  const [error, setError] = useState(null);

  useEffect(() => {
    setLoading(true);
    fetch("https://randomuser.me/api/?results=500")
      .then((res) => res.json())
      .then((res) => {
        setResults(res.results);
        setError(null);
      })
      .catch((e) => {
        setError(e);
      })
      .finally(() => {
        setLoading(false);
      });
  }, []);

  if (loading) return <div>Loading</div>;
  if (error) return <div>{error.message}</div>;

  return (
    <div>
      {results.map((item) => (
        <div key={item.id.value}>{item.name.first}</div>
      ))}
    </div>
  );
}
基本的には以下の通りです.
  • loading : データがフェッチされているかどうかを示す状態
  • results : 応答からデータを保持する状態
  • error : 何かがうまくいかないと誤りを記憶する状態
  • これらの状態で、我々は基本的に、上記のGIFでわかるように、API呼び出しプロセスを追跡することができます
    コンポーネント内にAPIコールがある場合はどうしますか?事態は乱雑になる.私たちは特定のAPIのためにより多くの州を必要とするでしょう.例えば、
    ...
    
    const [loading_1, setLoading_1] = useState(false);
    const [results_1, setResults_1] = useState([]);
    const [error_1, setError_1] = useState(null);
    
    const [loading_2, setLoading_2] = useState(false);
    const [results_2, setResults_2] = useState([]);
    const [error_2, setError_2] = useState(null);
    
    ...
    
    ここでの処理でいくつかの重複が得られたことがわかります.すべてのAPI呼び出しはloading , result and error 状態.我々がどうにか彼らを抽出することができて、我々が必要とするところでそれを再利用することができるならば、それは親切です.
    これは、カスタムフックが輝いている場所です.

    カスタムフック


    You should definitely checkout the tutorial from the official documentation here


    我々は最初にカスタムフックを理解する必要があります.下記のGIFを見てください

    あなたがイメージから見ることができるように、我々は非常に単純なプログラムを持っているtextarea . コードは次のようになります.
    import React, { useState, useEffect } from "react";
    
    export const WordCount = () => {
      const [value, setValue] = useState("");
      const [wordCount, setWordCount] = useState(0);
    
      // use useEffect to automatically recalculate the wordCount whenever the value changed
      useEffect(() => {
        setWordCount(value.trim() ? value.split(" ").length : 0);
      }, [value]);
    
      return (
        <div>
          <textarea
            style={{ width: "100%", height: 200 }}
            value={value}
            onChange={(event) => setValue(event.target.value)}
          />
          <div style={{ display: "flex", justifyContent: "space-between" }}>
            <button onClick={() => setValue("")}>Clear</button>
            <span>Word Count: {wordCount}</span>
          </div>
        </div>
      );
    };
    
    
    私たちも必要な場合はwordCount 他のコンポーネントの動作も?缶を再利用できますかwordCount どこか他のロジック?
    確かにはい🙂. 抽出しましょうwordCount カスタムフックにロジック.UseWordCountを見てください.jsファイル
    import { useState, useEffect } from "react";
    
    export const useWordCount = (textValue) => {
      const [count, setCount] = useState(0);
    
      // update the count state whenever textValue changed
      useEffect(() => {
        setCount(textValue.trim() ? textValue.split(" ").length : 0);
      }, [textValue]);
    
      return count;
    };
    
    今、我々はwordCount 論理分離.そして、基本的に我々は我々が望む任意のテキストを数えることができます.私たちのコンポーネントに戻って、カウントする必要があるいくつかのより多くの要素を追加します.我々の古いWordCount コンポーネントは次のようになります.
    import React, { useState } from "react";
    import { useWordCount } from "./useWordCount";
    
    export const WordCount = () => {
      const [textAreaValue, setTextAreaValue] = useState("");
      const [inputValue, setInputValue] = useState("");
    
      // Here is the count value we get from our custom hooks
      const textAreaCount = useWordCount(textAreaValue);
      const inputCount = useWordCount(inputValue);
    
      return (
        <div>
          <textarea
            style={{ width: "100%", height: 200 }}
            value={textAreaValue}
            onChange={(event) => setTextAreaValue(event.target.value)}
          />
          <div style={{ display: "flex", justifyContent: "space-between" }}>
            <button onClick={() => setTextAreaValue("")}>Clear</button>
            <span>Word Count: {textAreaCount}</span>
          </div>
          <div style={{ marginTop: 10 }}>
            <input
              type="text"
              value={inputValue}
              onChange={(e) => setInputValue(e.target.value)}
            />
            <span>Word Count: {inputCount}</span>
          </div>
        </div>
      );
    };
    
    
    すごい!結果を以下に示します.

    ご覧のように、クリーンなコードと、他のコンポーネントで使用できる再利用可能なフックがあります.

    カスタム呼び出しのAPI呼び出し問題


    ロジックの分離のためのカスタムフックを使用してアイデアを、私はAPIの呼び出し処理を簡素化するNPMパッケージを書いた.チェックアウトhttps://www.npmjs.com/package/react-hook-async

    インストール


    npm i react-hook-async
    
    or
    yarn add react-hook-async
    

    用途


    基本


    基本的なシナリオは、あなたの反応コンポーネント内でAPIを呼び出すことを試みているときです.
    import React, {useEffect} from 'react'
    import {useAsync} from 'react-hook-async'
    
    const fetchUsers = () =>
        fetch('https://randomuser.me/api/?results=50')
        .then((res) =>
          res.json()
        );
    
    export const ListUser = () => {
      const [apiData, executeFetchUsers] = useAsync([], fetchUsers)
    
      useEffect(() => {
        executeFetchUsers()
      }, [executeFetchUsers])
    
      const {loading, result, error} = apiData;
    
      if (loading) return <div>Loading</div>;
      if (error) return <div>{error.message}</div>;
    
      return (
        <div>
          {result.map((item) => (
            <div key={item.id.value}>{item.name.first}</div>
          ))}
        </div>
      );
    }
    
    我々は、我々のコンポーネントの中で3 - 4の状態を除去しました.😎
    解説:
  • The useAsync 配列を返します.
  • arrayの最初の要素は、API呼び出しプロセスのすべての状態を保持するオブジェクトですresult , error , loading and lastFetch . これなしでuseAsync , ローカル状態として保存する必要があります.
  • 返される配列の2番目の要素は、実際にAPIコールを実行するための関数です.
  • 基本的に、あなたは同じようなものについて考えることができましたuseState フックも同様の考えを持つ配列を返します:状態変数とこの状態を変更する関数です.
  • useAsync 2 argsをとります
  • 最初のargはresult フィールド.必要な値を渡すことができます.ここでは、型チェックを避けるために空の配列を使用しますresult が配列
  • 番目のargは実際に約束を返す関数です.あなたは、約束が内部で使われるので、機能が約束を返すことを確認しなければなりませんuseAsync フック.
  • 上の例から分かるように、現在では、useAsync , それを追跡するために内部状態を使用する必要なし.

    パラメータを渡す


    良いことは、“Execute”機能もパラメータを受け取ることができるということです、そして、彼らはあなたのAPI呼び出し機能に渡されます.以下のコードを見てみましょう.
    ...
    const fetchUsers = (numOfUser) =>
        fetch(`https://randomuser.me/api/?results=${numOfUser}`)
        .then((res) =>
          res.json()
        );
    
    export const ListUser = () => {
      const [apiData, executeFetchUsers] = useAsync([], fetchUsers)
    
      useEffect(() => {
        executeFetchUsers(50)
      }, [executeFetchUsers])
    
      const {loading, result, error} = apiData;
      ...
    }
    
    この機能を使えば、APIの呼び出し機能はカスタマイズされます.

    連鎖API呼び出しとエラー処理


    別の後にAPI呼び出しを実行したい場合や、呼び出し元のプロセスが完了/クラッシュした後に単にアクションを行う場合があります.The execute 関数は実際に約束を返し、さらにそれを解決したり、内部からのエラーを処理することができます.別の例を見ましょう.
    ...
    const fetchUsers = (numOfUser) =>
        fetch(`https://randomuser.me/api/?results=${numOfUser}`)
        .then((res) =>
          res.json()
        );
    
    const fetchFirstUser = (id) =>
        fetch(`https://randomuser.me/api/?id=${id}`)
        .then((res) =>
          res.json()
        );
    
    export const ListUser = () => {
      const [apiData, executeFetchUsers] = useAsync([], fetchUsers)
      const [firstUserApiData, executeFetchFirstUser] = useAsync(
        [],
        fetchFirstUser
      )
    
      useEffect(() => {
        executeFetchUsers(50)
          .then(users => executeFetchFirstUser(users[0].id))
          .catch(err => {
            console.log('Something went wrong:', err)
          })
      }, [executeFetchUsers, executeFetchFirstUser])
    
      const {loading, result, error} = apiData;
      ...
    }
    

    下流


    これまでの唯一の問題は、まあ、あなたはexecute DEPS配列の関数useEffect or useCallback , 私はかなりそれは決して変更されません確信していますが.あなたはおそらく、レポを訪問する可能性がhere 試してみてください.どんなprsも暖かく歓迎されます🙂

    結論


    反応フック、および独自のカスタムフックを作成する機能.あなたのコードベースは、はるかにクリーナーで、読みやすくなります.多くのライブラリのフックと簡単なアプローチに更新されています.あなたは間違いなくそれをチェックアウトする必要があります.

    参考

  • https://reactjs.org/docs/hooks-intro.html