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

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

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

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

React.js

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

Q&A

解決済

1回答

12059閲覧

React Hooksで useState内にデータが入らないとき

taihe-

総合スコア8

TypeScript

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

React.js

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

0グッド

0クリップ

投稿2019/11/23 12:10

const [userData, setUserData] = useState(); 1 const AddUserData = () => { 2 const replyPersonType = personal_info.personType; 3 const userInfo = guestInformations.find(doc => doc.id === personal_info.userId); 4 console.log(userInfo); 5 setUserData(userInfo); 6 console.log(userData) 7 }; 8 useEffect(() => { 9 AddUserData(); 10 console.log(userData) 11 }, []);

React Hooksレンダリングされる際に userInfoをstate内に入れる処理をしたいのですが

実行結果が

4  [object] 6  undefined 10 undefined

と変数内ではデータが取れているのに stateに入れた際におかしい挙動になってしまいます。

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

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

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

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

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

guest

回答1

0

ベストアンサー

こんにちは

以下は、公式ドキュメントから引用した、useEffectの説明です。

useEffect は毎回のレンダー後に呼ばれるのか? その通りです! デフォルトでは、副作用関数は初回のレンダー時および毎回の更新時に呼び出されます。あとでカスタマイズする方法について説明します。「マウント」と「更新」という観点で考えるのではなく、「レンダーの後」に副作用は起こる、というように考える方が簡単かもしれません。React は、副作用が実行される時点では DOM が正しく更新され終わっていることを保証します。

上記により、 一回目のuseEffect は初回のレンダーの後に呼ばれます。従って、初回のレンダーが行われる時点では、ご質問のコードにある userData は、useState() に引数を与えていないので、undefinedになります。初回のレンダーの後、useEffectが呼ばれて、AddUserData() が呼ばれ、setUserData() が呼ばれて、2回目のレンダー時では、userData に値が入っています。

以下は、ご質問にあるコードに多少修正を加えて、2回目のレンダー時には userData に値が入っていることを確認するサンプルコードです。

jsx

1// dummy data 2const guestInformations = [ 3 { id: 1, name: 'foo' }, 4 { id: 2, name: 'bar' }, 5 { id: 3, name: 'baz'} 6]; 7const personal_info = { userId: 2 }; 8 9// redering counter 10let counter = 0; 11 12const App = () => { 13 const [userData, setUserData] = useState(); 14 15 const AddUserData = () => { 16 const userInfo = guestInformations.find(doc => doc.id === personal_info.userId); 17 setUserData(userInfo); 18 } 19 20 useEffect(() => { 21 AddUserData(); 22 }, []); 23 24 console.log(`render#${++counter}: ${JSON.stringify(userData)}`) 25 26 return (<div>{JSON.stringify(userData)}</div>); 27}

Console に

render#1: undefined render#2: {'id':2,'name':'bar'}

と出力されるのが分かると思います。

上記のような挙動ではなく、初回のレンダー時から、有効な値の入った userDatauseState() から返させたいということであれば、useState()の引数として初期値を指定すればよいので、たとえば、以下のようにすればよいかと思います。

jsx

1 const userInfo = guestInformations.find(doc => doc.id === personal_info.userId); 2 const [userData, setUserData] = useState(userInfo);

上記のコードでは、 useEffectおよび setUserData を使っていないので、2回目のレンダーは発生せず、1回目のレンダー時から、userData にはundefinedではない値が入っていることを確認できます。

以上、参考になれば幸いです。

投稿2019/11/23 13:53

編集2019/11/23 14:00
jun68ykt

総合スコア9058

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問