🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
CSS3

CSS(Cascading Style Sheet)の第3版です。CSS3と略されることが多いです。色やデザインを柔軟に変更することが可能になります。

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

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

React.js

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

Q&A

解決済

1回答

1224閲覧

reactでコンポーネントの画像を複製したい

hello_whats_up

総合スコア57

CSS3

CSS(Cascading Style Sheet)の第3版です。CSS3と略されることが多いです。色やデザインを柔軟に変更することが可能になります。

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

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

React.js

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

1グッド

0クリップ

投稿2019/09/10 01:20

編集2019/09/10 04:44

実現したいこと

reactでコンポーネントを複製したい。(コンポーネントの大枠は同じだが、中にある画像や文字は変更したい)
APIからとってきたJSONの文字や画像の複数の情報を使用して同じようなコンポーネントを複製したいです。

例えば、その情報をstateに設定してsetStateするたびにrenderが呼び出されるようにしたら良いのかと思ったのですが、うまくいきませんでしたでした。
解決策やアイデアが有りましたら教えて下さい。よろしくお願いいたします。

失敗したコードと、返ってくるJSONの例です。
このようにしたら順にsetStateできると思ったのですが、setStateされるたびにrenderを呼び出す方法がわかりませんでした。

ご指摘お願いします。

React

1axios 2 .get( ENDPOINT, { 3 headers: { "Content-Type": "application/json" }, 4 data: {}, 5 }) 6 .then( (res) => { 7 for(var i=0; i < res.data.array.length; ++ i ){ 8 this.setState({ 9 name: res.data.array[i].name, 10 storeId: res.data.array[i].id 11 }) 12 } 13 })

JOSN

1{ 2 "array": [ 3 { 4 "id": 1, 5 "name": "パン屋" 6 }, 7 { 8 "id": 2, 9 "name": "弁当屋" 10 }, 11 { 12 "id": 3, 13 "name": "カレー屋" 14 }, 15 { 16 "id": 4, 17 "name": "肉屋" 18 }, 19 { 20 "id": 5, 21 "name": "八百屋" 22 } 23 ], 24 "foodNum": 5, 25 "userId": 1 26}
jun68ykt👍を押しています

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

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

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

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

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

jun68ykt

2019/09/10 04:10

こんにちは。可能であれば、 APIが返すJSONのサンプルと、「うまくいきませんでした」との、うまく動かなかったコードも質問に追記頂けると、pokopoko_7さんにとって有益な回答がつきやすくなると思います。
hello_whats_up

2019/09/10 04:40

修正しました。 ご指摘ありがとうございます。
jun68ykt

2019/09/10 05:36

追記ありがとうございます。 このような JSON を受け取って、実現したいこととしては、render されるHTMLが、たとえば <div class="item"> <div>ID: 1</div><div>名前: パン屋</div> </div> といったような、 itemクラスの <div> が、 id 1 から 5 までの5個並び、ソースコードとしては、 itemクラスの <div> のくくりを <Item id="1" name="パン屋" /> みたいな感じで書きたい、 という感じでしょうか?
hello_whats_up

2019/09/10 05:44

はい、イメージとしてはそのような感じです。
jun68ykt

2019/09/10 16:15

なるほどです。上記の趣旨にそったソースコードのサンプル含めて、回答しました。
hello_whats_up

2019/09/11 08:46

ありがとうございます、うまくいきました! もう少し基本を学びなおします。
jun68ykt

2019/09/11 08:58

> うまくいきました! とのことでよかったです。 > もう少し基本を学びなおします。 はい。それは良い取り組みだと思います。
guest

回答1

0

ベストアンサー

こんにちは

まず、ご質問に書かれている現状について、指摘させて頂きますと、まず第一に

このようにしたら順にsetStateできると思ったのですが、setStateされるたびにrenderを呼び出す方法がわかりませんでした。

とのことですが、Reactのユーザー自身が、

setStateされるたびにrenderを呼び出す

ためのコードを書く必要はないです。というのは、 setState によって this.state に変更があったら、自動的にrenderを呼んでくれる仕組みをReactが提供してくれているからです。

次に、ご質問に挙げられているコードの以下の部分

javascript

1 for(var i=0; i < res.data.array.length; ++ i ){ 2 this.setState({ 3 name: res.data.array[i].name, 4 storeId: res.data.array[i].id 5 }) 6 }

で、array の要素をループでひとつひとつ取得して、各々に対して setStateしていますが、これだとループが終わったときに、this.state に入っているのは最後の要素の情報だけになってしまいますので、APIのレスポンスが返ってきたら、レスポンスに入っている arrayをそのまま this.state.arrayとして保持させるようにします。したがって、レスポンスが返ってきたら、それに応じた setState は1回ということになります。

上記をふまえて、以下は具体的なサンプルです。
(ENDPOINT としては、モックAPIサービスのmockable.io に、ご質問にあるJSONを返すように作成しました。)

App.js

jsx

1import React from 'react'; 2import axios from 'axios'; 3import './style.css'; 4 5const ENDPOINT = 'https://demo2746340.mockable.io/q211055/data1.json'; 6 7const Item = ({ id, name }) => ( 8 <tr> 9 <td>{id}</td> 10 <td>{name}</td> 11 </tr> 12); 13 14class App extends React.Component { 15 constructor(props) { 16 super(props) 17 this.state = { array: [] } 18 } 19 20 componentDidMount() { 21 axios 22 .get(ENDPOINT) 23 .then(res => { 24 this.setState({ array: res.data.array }); 25 }) 26 } 27 28 render() { 29 return ( 30 <table> 31 <tr><th>ID</th><th>NAME</th></tr> 32 {this.state.array.map(e => 33 <Item key={e.id} id={e.id} name={e.name} />) 34 } 35 </table> 36 ); 37 } 38} 39 40export default App;

上記では、JSONの内容を <table> による表にしています。 <Item>arrayに含まれる要素の1個分の内容をrenderするためのFunctionalコンポーネントで、テーブルの1行分になります。

以下は、App を動作確認するためのいくつかのファイルです。

index.html

html

1<!DOCTYPE html> 2<html lang="ja"> 3 <head> 4 <title>sample</title> 5 </head> 6 <body> 7 <div id="root"></div> 8 </body> 9</html>

index.js

javascript

1import React from 'react'; 2import ReactDOM from 'react-dom'; 3import App from './App'; 4 5ReactDOM.render(<App />, document.getElementById('root'));

style.css

css

1table, th, td { border: solid 1px #000; } 2table { border-collapse: collapse; } 3td, th { padding: 10px; } 4th { background-color: #aaa; }

AppがJSONの内容を<table>として表示するまでの基本的な流れは以下です。

  1. 初回のrender では、this.state.array は空の配列です。これはconstructorでそのように初期化されているからです。したがって、ヘッダ行のみのテーブルがrender されます。
  2. 初回のrenderが終わった後、componentDidMountが呼ばれ、その中でaxiosがENDPOINT からJSONをGETしようとします。
  3. JSONの取得が成功すると、レスポンスに含まれる array を this.state.array として保持するようにsetStateします。配列全体でstateを更新するので、setStateは一回です。
  4. setState によってthis.state が更新されると、再度renderが(冒頭書いたように、自動的に)呼ばれます。
  5. 再度のrenderのときは this.state.array は空ではなく、axiosによるGETのレスポンスJSONに含まれるarray の内容に更新されています。これに map を使うことで、 <Item> の配列を得ます。
  6. <Item> は、データ行の1行分にrender されるので、App全体としては以下のように表示されます。

イメージ説明

まとめますと、まずは冒頭に書いた

  • setState によって this.state の内容が変更されたら、自動的にrenderを呼んでくれる仕組みをReactが提供してくれている

という点をしっかり押さえておき、その上で、コンポーネントの(componentDidMountなどの)ライフサイクルメソッドの理解を点検するとよいかと思います。

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

追記

このご質問で確認しておく必要のある内容は Reactの基本ですので、公式ドキュメントを拠り所にすることをお勧めします。このご質問の疑問を解消するという目的ですと、 MAIN COCEPTS の章の

あたりです。上記のページで、「クラスにライフサイクルメソッドを追加する 」の節の終わりに、 Clockの完成版について動作の流れが 1. 〜 5. として順に説明されています。その中で

  1. ・・・ setState() が呼び出されたおかげで、React は state が変わったということが分かるので、render() メソッドを再度呼び出して、画面上に何を表示すべきかを知ります。・・・

と書かれており、上記の原文 は、

4.・・・ Thanks to the setState() call, React knows the state has changed, and calls the render() method again to learn what should be on the screen. ・・・

と書かれています。この中の

Thanks to the setState() call, React knows the state has changed, and calls the render() method again

のことを、私の回答の冒頭では

setState によって this.state に変更があったら、自動的にrenderを呼んでくれる仕組みをReactが提供してくれている

と表現しました。

投稿2019/09/10 16:13

編集2019/09/11 05:20
jun68ykt

総合スコア9058

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問