質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

2回答

4446閲覧

TypeScript+React Hooksでのフックをラップしたい

tabasco_w

総合スコア1

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

0クリップ

投稿2020/06/24 18:18

最近TypeScriptを学び始め、TypeScript+React HooksでWebアプリを作っています。
その中で、コーディングミスを減らす為にとあるフックの引数を型安全にするためにラップ関数を作りたいと考えました。
しかし、フックを呼び出せるのはトップレベルまたはカスタムフックのみという制約から、フックのラッパをうまく定義することができませんでした。

フックをラップして型安全にする、または同等の処理を実現する方法などありましたらご教示いただきたいです。

以下その制約を回避するために行った試行錯誤です。(ちなみに今回対象のフックはreact-router-domのuseHistoryです)

該当フックを2重にラップするパターン

TypeScript

1const useRedirect = () => (nextPage: '/' | '/about') => useHistory().push(nextPage);

しかし、こちらのパターンはフックの制約から下記エラーで弾かれてしまいます。

Error

1React Hook "useHistory" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function react-hooks/rules-of-hooks
該当フック直接呼び出すパターン

TypeScript

1const useRedirect = (nextPage: '/' | '/about') => useHistory().push(nextPage);

こちらは呼び出し元のトップレベルで実行する場合は問題ありませんが、コールバックの中などから呼び出すと下記エラーで弾かれました。

Error

1React Hook "useRedirect" is called in function "myCallback" which is neither a React function component or a custom React Hook function react-hooks/rules-of-hooks
ラッパの内側の関数をカスタムフックに見せかけるパターン

TypeScript

1const useRedirect = () => function useR(nextPage: '/' | '/about') { useHistory().push(page) };

こちらコンパイルは通りましたが、結局入れ子にした関数からフックを呼び出している状態のため実行時に下記エラーとなりました。
コンパイラを騙して実行時にエラーを残したので一番悪いパターンです。

Error

1Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: 21. You might have mismatching versions of React and the renderer (such as React DOM) 32. You might be breaking the Rules of Hooks 43. You might have more than one copy of React in the same app 5See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hoshi-takanori

2020/06/24 19:54 編集

コメント取り消します。
maisumakun

2020/06/24 22:22

当該のフックを「使う側」のコードはどのように書いていますか?
guest

回答2

0

こちらは呼び出し元のトップレベルで実行する場合は問題ありませんが、コールバックの中などから呼び出すと下記エラーで弾かれました。

はい、カスタムフックは「関数コンポーネントのトップレベル」もしくは「別なカスタムフック」からしか呼べません。コールバックから呼んではいけないので、警告が正しいです。

投稿2020/06/24 22:19

maisumakun

総合スコア146018

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

カスタムフックから別のフック関数を呼ぶ場合、カスタムフックが返す関数の中ではなく、カスタムフック自体から呼ぶ必要があります。つまり、以下のようにすればいいはず。

js

1const useRedirect = () => { 2 const history = useHistory(); 3 return (nextPage: '/' | '/about') => history.push(nextPage); 4}

投稿2020/06/24 19:54

hoshi-takanori

総合スコア7901

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tabasco_w

2020/06/25 00:41

何か固定概念に囚われていたようです。 提示されてみればまさにその通りで、よく目にするフックの書き方そのものでした。 カスタムフックについて理解が甘かったようなので勉強し直そうと思います。 ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問