独自のUsefetchフックを書く


反応フックは、1年以上少しの間、すべての怒りでした.我々がどのように我々自身を巻くことができるかについて見ましょうuseFetch フックへのフックは、我々のコンポーネントから要求論理を要求します.
注:これは学術目的のためだけです.あなた自身のロールuseFetch フックと生産でそれを使用するが、私は非常に確立されたライブラリを使用してお勧めしますuse-http あなたのために重いリフトを行うには!

この投稿をお楽しみください💓, 🦄, or 🔖 そしてサインアップを検討する📬 my free weekly dev newsletter

Usefetch関数シグネチャ
決定するuseFetch 関数シグネチャは、エンドユーザーから実際にフェッチ要求を実行するために必要な情報を考慮する必要があります.この場合、我々はリソースを必要とすると言いますurl そして、我々はoptions これはリクエスト(例えばリクエストメソッド)と一緒に行われるかもしれません.
function useFetch(initialUrl, initialOptions) {
  // Hook here
}
よりフル機能のソリューションでは、ユーザーに要求を中止する方法を与えるかもしれませんが、我々は現在の2つの引数に満足している!

フックの状態維持
我々のフックは、若干の州を維持する必要がありそうです.我々は少なくとも維持する必要があるurl and options 我々のユーザーに道を与える必要があるようにsetUrl and setOptions ). いくつかの他のステキトフル変数は、我々は同様にしたいです!
  • データ(リクエストから返されるデータ)
  • エラー(リクエストが失敗した場合にエラーが発生します)
  • load (アクティブにフェッチしているかどうかを示すboolean値)
  • を使用してstatutive変数の束を作成しましょうuseState フック.また、ユーザに以下のことをする機会を与えたいと思います.
  • URLを設定する
  • オプションを設定する
  • 取得したデータを見る
  • エラーを見る
  • 読み込みステータス
  • したがって、我々はこれらの2つの状態設定機能と我々のフックからの3つのデータを返すようにしなければなりません!
    import { useState } from 'React';
    
    function useFetch(initialUrl, initialOptions) {
      const [url, setUrl] = useState(initialUrl);
      const [options, setOptions] = useState(initialOptions);
      const [data, setData] = useState();
      const [error, setError] = useState();
      const [loading, setLoading] = useState(false);
    
      // Some magic happens here
    
      return { data, error, loading, setUrl, setOptions };
    }
    
    重要なのは、デフォルトurl and optionsinitialUrl and initialOptions フックが最初に呼ばれるとき、提供されます.また、これらは多くの異なる変数であると考えているかもしれません、そして、あなたは同じオブジェクト、またはいくつかのオブジェクトでそれらをすべて維持したいです、そして、それは全くすばらしいです!

    URLまたはオプションの変更時に効果を実行する
    これはかなり重要な部分です!我々は、Aを実行したいですfetch 毎回リクエストするurl or options 変数変更.何より良い方法を行うには、ビルトインuseEffect フック?
    import { useState } from 'React';
    
    function useFetch(initialUrl, initialOptions) {
      const [url, setUrl] = useState(initialUrl);
      const [options, setOptions] = useState(initialOptions);
      const [data, setData] = useState();
      const [error, setError] = useState();
      const [loading, setLoading] = useState(false);
    
      useEffect(() => {
        // Fetch here
      }, [url, options]);
    
      return { data, error, loading, setUrl, setOptions };
    }
    

    を返します.
    私は約束構文の上でasync/wait構文を好むので、前者を使いましょう!これはもちろん、使用だけでなく、then , catch , and finally async/waitよりむしろ.
    import { useState } from 'React';
    
    function useFetch(initialUrl, initialOptions) {
      const [url, setUrl] = useState(initialUrl);
      const [options, setOptions] = useState(initialOptions);
      const [data, setData] = useState();
      const [error, setError] = useState();
      const [loading, setLoading] = useState(false);
    
      useEffect(() => {
        setLoading(true);
        setError(undefined);
    
        async function fetchData() {
          try {
            const res = await fetch(url, options);
            const json = await res.json();
            setData(json);
          } catch (e) {
            setError(e);
          }
          setLoading(false);
        }
        fetchData();
      }, [url, options]);
    
      return { data, error, loading, setUrl, setOptions };
    }
    
    それはたくさんだった!少しそれを壊しましょう.我々の効果を実行するとき、我々はデータを取得し始めていることを知っている.したがって、私たちはloading 変数true そして、我々は以前に存在したかもしれないどんな誤りも明らかにします.
    我々のasync機能で、我々は我々を包みますfetch リクエストコードtry/catch ブロック.我々が得るどんなエラーでも、我々にユーザーに報告したいですcatch ブロックsetError どんなエラーにも報告されます.
    我々の中でtry ブロック、我々は公正な標準を行うfetch リクエスト.返されるデータはjson 私が怠惰なので、しかし、我々がこれを最も融通がきくフックにしようとしていたならば、我々はおそらく我々のユーザーに予想されたレスポンスタイプを構成する方法を与えます.最後に、すべてが成功したと仮定して、我々は我々をセットしましたdata 我々の返されたJSONに変数!

    フックの使用
    信じているかどうか、それはすべて私たちのカスタムフックを作成することです!今、我々はちょうどサンプルアプリケーションにそれをもたらすとそれが動作することを期待する必要があります.
    次の例では、任意のGithubユーザーの基本的なGitHubプロファイルデータを読み込むアプリケーションがあります.このアプリは、我々の設定の例外を使用してフックのために設計されたほとんどすべての機能を曲げてfetch オプション.フェッチ要求がロードされている間に、「ローディング」インジケーターを表示することができます.取得が完了すると、結果のエラーや結果の文字列化されたバージョンを表示します.
    私たちはユーザーに新しいフェッチを実行するために別のgithubのユーザー名を入力する方法を提供します.一度提出すると、我々はsetUrl 関数のエクスポートuseFetch フックは、効果を実行し、新しい要求を行う原因となります.我々はすぐに新しいデータがある!
    const makeUserUrl = user => `https://api.github.com/users/${user}`;
    
    function App() {
      const { data, error, loading, setUrl } = useFetch(makeUserUrl('nas5w'));
      const [user, setUser] = useState('');
    
      return (
        <>
          <label htmlFor="user">Find user:</label>
          <br />
          <form
            onSubmit={e => {
              e.preventDefault();
              setUrl(makeUserUrl(user));
              setUser('');
            }}
          >
            <input
              id="user"
              value={user}
              onChange={e => {
                setUser(e.target.value);
              }}
            />
            <button>Find</button>
          </form>
          <p>{loading ? 'Loading...' : error?.message || JSON.stringify(data)}</p>
        </>
      );
    }
    
    お気軽にチェックアウトuseFetch フックとサンプルアプリケーションon codesandbox here .

    思考の結論
    カスタム反応フックを書くことは楽しい努力することができます.それは時々最初に少しトリッキーですが、一度それは非常に楽しいのハングアップを取得し、本当に短縮し、コンポーネントのコードの冗長性を減らすことができます.
    あなたがこのフックについての質問をするならば、反応してください、あるいは、一般的に、JSは躊躇しないでください!