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

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

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

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

React.js

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

Q&A

解決済

2回答

1656閲覧

関数が返すオブジェクトの値をレンダリングしたいです。

evgenia

総合スコア28

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

React.js

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

0グッド

0クリップ

投稿2020/06/25 08:07

前提・実現したいこと

下記のサンプルは1〜3の数字の配列から、数字とその数字が偶数かを丸バツで判定したリストをレンダリングするものです。
CodeSandBoxで作成しました。
サンプル

関数が返すオブジェクトの値をレンダリングしたいです。

発生している問題・エラーメッセージ

エラーは発生していませんが、各値が空の状態でレンダリングされています。

該当のソースコード

jsx

1const array = [1, 2, 3]; 2 3const App = () => { 4 const renderArray = array.map(num => { 5 const checkEvenNum = async num => { 6 const result = num % 2; 7 const resultObj = await getResultObj(result); 8 return resultObj; 9 }; 10 11 const getResultObj = async result => { 12 if (result === 0) return { check: "○", num: num }; 13 return { check: "×", num: num }; 14 }; 15 16 return ( 17 <li key={num}> 18 <p>数字: {checkEvenNum(num).num}</p> 19 <p>偶数: {checkEvenNum(num).check}</p> 20 </li> 21 ); 22 }); 23 24 return <ul>{renderArray}</ul>; 25};

試したこと

関数の実行が終わる前にレンダリングされるため値が空なのかなと思い、下記のようにasync/awaitを加えました

jsx

1const renderArray = array.map(async num => { 2... 3 4return ( 5 <li key={num}> 6 <p>数字: {await checkEvenNum(num).num}</p> 7 <p>偶数: {await checkEvenNum(num).check}</p> 8 </li> 9);

すると、下記のエラーが表示されました。

Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead. in ul (at App.js:26) in App (at src/index.js:9) in StrictMode (at src/index.js:8)

エラーメッセージをそのまま検索すると、原因はpropsの受け取りを{}で囲っていないため、という旨の記事を見つけたのですが、propsを受け取るコンポーネントが無いので、原因がわかりませんでした。

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

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

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

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

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

guest

回答2

0

ベストアンサー

awaitは実はasync関数の結果を出すことではなく、そのあとのコードを変形することです。だから React JSX の HTML の部分では用いられません。

ただ希望通りレンダリングしたいのなら、asyncawaitを全部外したら大丈夫です。

勉強のためにasync/awaitを用いたいのなら、useStateuseEffectを使わなければならないのです。

まずはmapの中身を独立します。そうしないとuseStateuseEffectを使えません。

jsx

1const NumberDisplay = ({ num }) => { 2 const checkEvenNum = async num => { 3 const result = num % 2; 4 const resultObj = await getResultObj(result); 5 return resultObj; 6 }; 7 8 const getResultObj = async result => { 9 if (result === 0) return { check: "○", num: num }; 10 return { check: "×", num: num }; 11 }; 12 13 return ( 14 <li key={num}> 15 <p>数字: {checkEvenNum(num).num}</p> 16 <p>偶数: {checkEvenNum(num).check}</p> 17 </li> 18 ); 19}; 20 21const App = () => { 22 const renderArray = array.map(num => { 23 return <NumberDisplay num={num} />; 24 }); 25 26 return <ul>{renderArray}</ul>; 27};

checkEvenNum()の結果を直接使えないので、useStateを使ってstateを作ります。後でcheckEvenNum()の結果をsetStatestateに入れます。

jsx

1const NumberDisplay = ({ num }) => { 2 const [state, setState] = useState({}); 3 4 const checkEvenNum = async num => { 5 const result = num % 2; 6 const resultObj = await getResultObj(result); 7 return resultObj; 8 }; 9 10 const getResultObj = async result => { 11 if (result === 0) return { check: "○", num: num }; 12 return { check: "×", num: num }; 13 }; 14 15 return ( 16 <li key={num}> 17 <p>数字: {state.num}</p> 18 <p>偶数: {state.check}</p> 19 </li> 20 ); 21};

useEffectを使って、asyncgetResultObjcheckEvenNumを中身にして、結果をsetStatestateに入れます。useEffectの2つ目の引数は依存リストであり、numsetStateを中身に使うから入れます。

jsx

1const NumberDisplay = ({ num }) => { 2 const [state, setState] = useState({}); 3 4 useEffect(() => { 5 const checkEvenNum = async num => { 6 const result = num % 2; 7 const resultObj = await getResultObj(result); 8 return resultObj; 9 }; 10 const getResultObj = async result => { 11 if (result === 0) return { check: "○", num: num }; 12 return { check: "×", num: num }; 13 }; 14 const eff = async () => { 15 setState(await checkEvenNum(num)); 16 }; 17 eff(); 18 }, [num, setState]); 19 20 return ( 21 <li key={num}> 22 <p>数字: {state.num}</p> 23 <p>偶数: {state.check}</p> 24 </li> 25 ); 26};

最後の結果のCode Sandbox

お役に立てたら幸いです。

投稿2020/06/25 08:58

YufanLou

総合スコア464

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

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

evgenia

2020/06/25 09:43

ご回答とコードをご提供くださりありがとうございました!実装できかつ理解できました。重ねて御礼申し上げます。
guest

0

エラーメッセージをそのまま検索すると、原因はpropsの受け取りを{}で囲っていないため、という旨の記事を見つけたのですが

違います。ReactのJSXに直接Promiseを混ぜ込んでしまったのが原因です。

各値が空の状態でレンダリングされています。

async関数の返り値はPromiseなので、返り値から直接プロパティを取得することはできません。


コンポーネントの中でできることは、いったんstateを立てて、Promiseresolveした時点でsetStateを行う、ような間接的な手段しかないかと思います。

投稿2020/06/25 08:11

maisumakun

総合スコア146018

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

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

evgenia

2020/06/25 08:51

ご回答いただきありがとうございます。array.map内でsetStateでオブジェクトを格納したところ、次のエラーが表示されました。Too many re-renders. React limits the number of renders to prevent an infinite loop. setStateを使用する場合のコードをご教示いただけないでしょうか。
maisumakun

2020/06/25 08:54

getResultObjがコンポーネント内に置かれていますが、これは何かしらの意図があってのものでしょうか?それとも、「別に外側にあっても構わない」ものでしょうか?
evgenia

2020/06/25 08:58 編集

外側にあっても構わないものです。意図はありません。
maisumakun

2020/06/25 09:04

> setStateを使用する場合のコードをご教示いただけないでしょうか。 ここで書くには長くなりすぎます。array.mapの中身を1つのコンポーネントとしてくくりだす必要があります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問