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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Next.js

Next.jsは、Reactを用いたサーバサイドレンダリングなどを行う軽量なフレームワークです。Zeit社が開発しており、nextコマンドでプロジェクトを作成することにより、開発環境整備が整った環境が即時に作成できます。

React.js

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

Q&A

解決済

2回答

1619閲覧

[React]定義したカスタムフックの戻り値が空のオブジェクトになってしまう

sabx

総合スコア200

Next.js

Next.jsは、Reactを用いたサーバサイドレンダリングなどを行う軽量なフレームワークです。Zeit社が開発しており、nextコマンドでプロジェクトを作成することにより、開発環境整備が整った環境が即時に作成できます。

React.js

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

0グッド

0クリップ

投稿2020/11/20 04:08

聞きたいこと

React/NextjsにてWebアプリを作成しています。
pageコンポーネントにて定義していたロジックを、カスタムコンポーネントに移動した際に動作しなくなってしまったため質問させてください。

詳細

もともとページコンポーネントに実装していた内容は下のとおりです。

  • pages/index.ts

javascript

1import * as React from 'react'; 2import { useRouter } from 'next/router'; 3 4// これはバックエンドAPIと疎通してユーザー情報を取得する関数です 5import { fetchUser } from '@/repositories'; 6: 7 8const Index: React.FC = (): React.ReactElement => { 9 const router = useRouter(); 10 const { id } = router.query; 11 let user = {}; 12 13 React.useEffect(() => { 14 fetchUser(id).then((u) => { 15 user = u; 16 }) 17 }, [router]) 18 19 return ( 20 <div>Index Page {user}</div> 21 ) 22}

上で実装したuseEffectの部分をカスタムフックとして外出しした結果が下のとおりです。

  • pages/index.ts

javascript

1import * as React from 'react'; 2 3: 4 5const Index: React.FC = (): React.ReactElement => { 6 const user = useUser(); 7 8 return ( 9 <div>Index Page {user}</div> 10 ) 11}
  • hooks/index.ts
import * as React from 'react'; import { useRouter } from 'next/router'; import { fetchUser } from '@/repositories'; : export const useUser = () => { const router = useRouter(); const { id } = router.query; let user = {}; React.useEffect(() => { fetchUser(id).then((u) => { user = u; }) }, [router]) return user; } :

カスタムフック移行後は、カスタムフック内で定義したuser変数を返すようにしていますが、
pageコンポーネント内で表示すると、user変数の初期値である空のオブジェクトになってしまいます。

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

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

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

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

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

guest

回答2

0

Reactでデータの状態を管理するにはuseStateを使う必要があります
次のようにすれば正しく変更されるはずです

ts

1export const useUser = () => { 2 const router = useRouter(); 3 const { id } = router.query; 4 const [user, setUser] = React.useState({}); 5 6 React.useEffect(() => { 7 fetchUser(id).then((u) => { 8 setUser(u) 9 }) 10 }, [router]) 11 12 return user; 13}

投稿2020/12/17 06:48

mikan3rd

総合スコア220

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

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

0

ベストアンサー

useEffect の動きから考えてみましょう。最初の例では router が変更されることによって useEffect に渡された関数が発火し user が変更されてそれが表示に反映される、という仕組みですね。

これを二番目のようにカスタムフックに切り出すと何が起こるかと言うと router の変更によって useEffect に渡された関数が発火し user が変更されるところまでは変わりません。ところがこのカスタムフックでは早々に user に最初から入っている {} を返し役目を終えてしまいます。React はカスタムフック内にいる単なる「値」である user の変更までは追うことができません。ではどのように解決すべきでしょうか。

考えてみるとこの関数は user という「状態」を持っていることになります。つまり useState を使えばこの状態を外に持ち出すことができます。

JavaScript

1export const useUser = () => { 2 const router = useRouter(); 3 const { id } = router.query; 4 const [user, setUser] = useState({}); 5 6 React.useEffect(() => { 7 fetchUser(id).then((u) => { 8 user = u; 9 }) 10 setState(u); 11 }, [router]) 12 13 return user; 14}

この場合も user は単なる値ですが、setUser を使い React によって更新されうる点が違います。一番目の例でも状態を持つことができますが、状態を持つ場合明示的に useState を使ったほうが見通しが良くなるでしょう。

投稿2020/12/17 06:35

編集2020/12/17 06:41
A_kirisaki

総合スコア2853

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問