こんにちは
まず、ご質問に書かれている現状について、指摘させて頂きますと、まず第一に
このようにしたら順に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>として表示するまでの基本的な流れは以下です。
- 初回の
render では、this.state.array は空の配列です。これはconstructorでそのように初期化されているからです。したがって、ヘッダ行のみのテーブルがrender されます。
- 初回の
renderが終わった後、componentDidMountが呼ばれ、その中でaxiosがENDPOINT からJSONをGETしようとします。
- JSONの取得が成功すると、レスポンスに含まれる array を
this.state.array として保持するようにsetStateします。配列全体でstateを更新するので、setStateは一回です。
setState によってthis.state が更新されると、再度renderが(冒頭書いたように、自動的に)呼ばれます。
- 再度の
renderのときは this.state.array は空ではなく、axiosによるGETのレスポンスJSONに含まれるarray の内容に更新されています。これに map を使うことで、 <Item> の配列を得ます。
- 各
<Item> は、データ行の1行分にrender されるので、App全体としては以下のように表示されます。

まとめますと、まずは冒頭に書いた
setState によって this.state の内容が変更されたら、自動的にrenderを呼んでくれる仕組みをReactが提供してくれている
という点をしっかり押さえておき、その上で、コンポーネントの(componentDidMountなどの)ライフサイクルメソッドの理解を点検するとよいかと思います。
以上、参考になれば幸いです。
追記
このご質問で確認しておく必要のある内容は Reactの基本ですので、公式ドキュメントを拠り所にすることをお勧めします。このご質問の疑問を解消するという目的ですと、 MAIN COCEPTS の章の
あたりです。上記のページで、「クラスにライフサイクルメソッドを追加する 」の節の終わりに、 Clockの完成版について動作の流れが 1. 〜 5. として順に説明されています。その中で
- ・・・ 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が提供してくれている
と表現しました。