回答編集履歴

4

テキスト追加

2021/11/25 14:02

投稿

退会済みユーザー
test CHANGED
@@ -193,3 +193,157 @@
193
193
 
194
194
 
195
195
  - **動作確認のサンプル** ???? [tera: 370866 without lodash](https://codepen.io/kilesa/pen/KKvjBvN?editors=0010) @codepen
196
+
197
+
198
+
199
+
200
+
201
+ ### 追記2
202
+
203
+
204
+
205
+ 上記の回答で、codepenに挙げたコード(のlodashを使うほう)をお手元で試すには、以下の手順で実行できるかと思います。
206
+
207
+
208
+
209
+ #### (1) 依存モジュールのインストール
210
+
211
+
212
+
213
+ ```shell
214
+
215
+ npm install lodash
216
+
217
+ ```
218
+
219
+
220
+
221
+ axios はすでにインスト−ルされているかと思いますが、まだであれば、
222
+
223
+
224
+
225
+ ```shell
226
+
227
+ npm install axios
228
+
229
+ ```
230
+
231
+
232
+
233
+ #### (2) src/components/ApiFetch.js を作成
234
+
235
+
236
+
237
+ 以下のように作成します。
238
+
239
+ ```jsx
240
+
241
+ import { useEffect, useState } from 'react';
242
+
243
+ import axios from 'axios';
244
+
245
+ import _ from 'lodash';
246
+
247
+
248
+
249
+ const POSTS_URL = 'https://jsonplaceholder.typicode.com/posts';
250
+
251
+ const COMMENTS_URL = 'https://jsonplaceholder.typicode.com/comments';
252
+
253
+
254
+
255
+ const merge = (posts, comments, maxPostId) => {
256
+
257
+
258
+
259
+ const filteredComments = comments.filter(({ postId }) => postId <= maxPostId);
260
+
261
+
262
+
263
+ const groupByPost = _(filteredComments)
264
+
265
+ .groupBy('postId')
266
+
267
+ .mapValues(
268
+
269
+ (comments, postId) => ({
270
+
271
+ ...posts.find(({ id }) => id === +postId),
272
+
273
+ comments
274
+
275
+ })
276
+
277
+ )
278
+
279
+ .value();
280
+
281
+
282
+
283
+ return groupByPost;
284
+
285
+ }
286
+
287
+
288
+
289
+ const ApiFetch = () => {
290
+
291
+
292
+
293
+ const [posts, setPosts] = useState({});
294
+
295
+
296
+
297
+ useEffect(() => {
298
+
299
+ const urls = [POSTS_URL, COMMENTS_URL];
300
+
301
+ const fetchers = urls.map(url => axios.get(url));
302
+
303
+ Promise.all(fetchers).then(([{ data: posts }, { data: comments }]) => {
304
+
305
+ const mergedPosts = merge(posts, comments, 50);
306
+
307
+ setPosts(mergedPosts);
308
+
309
+ });
310
+
311
+ }, []);
312
+
313
+
314
+
315
+ return (
316
+
317
+ <pre id="posts">
318
+
319
+ {JSON.stringify(posts, null, 4)}
320
+
321
+ </pre>
322
+
323
+ );
324
+
325
+ }
326
+
327
+
328
+
329
+ export default ApiFetch;
330
+
331
+
332
+
333
+ ```
334
+
335
+
336
+
337
+ ### (3) App.jsからApiFetchをimport
338
+
339
+
340
+
341
+ これで、`App.js`で、
342
+
343
+ ```javascript
344
+
345
+ import ApiFetch from './components/ApiFetch';
346
+
347
+ ```
348
+
349
+ とすることで、Appの返すJSXの中で、`<ApiFetch />` をどこかに書けば、動作確認できると思われます。

3

テキスト追加

2021/11/25 14:02

投稿

退会済みユーザー
test CHANGED
@@ -172,23 +172,19 @@
172
172
 
173
173
  posts.slice(0, maxPostCount)
174
174
 
175
- .reduce((obj, post) => (
175
+ .reduce((obj, post) => {
176
176
 
177
- {
177
+ obj[post.id] = {
178
178
 
179
- ...obj,
179
+ ...post,
180
180
 
181
- [post.id]: {
181
+ comments: comments.filter(({ postId }) => post.id === postId)
182
182
 
183
- ...post,
183
+ };
184
184
 
185
- comments: comments.filter(({ postId }) => post.id === postId)
185
+ return obj;
186
186
 
187
- }
188
-
189
- }
190
-
191
- ), {});
187
+ }, {});
192
188
 
193
189
  ```
194
190
 
@@ -196,4 +192,4 @@
196
192
 
197
193
 
198
194
 
199
- - **動作確認のサンプル** ???? [tera: 370866 without lodash](https://codepen.io/kilesa/pen/QWMXxxe?editors=0010) @codepen
195
+ - **動作確認のサンプル** ???? [tera: 370866 without lodash](https://codepen.io/kilesa/pen/KKvjBvN?editors=0010) @codepen

2

テキスト追加

2021/11/24 22:51

投稿

退会済みユーザー
test CHANGED
@@ -153,3 +153,47 @@
153
153
  });
154
154
 
155
155
  ```
156
+
157
+
158
+
159
+
160
+
161
+ ### 追記
162
+
163
+
164
+
165
+ 上記の (1) で、lodash を使うコードを回答しましたが、lodashを使わない `merge`関数のコード例も挙げておきます。
166
+
167
+
168
+
169
+ ```javascript
170
+
171
+ const merge = (posts, comments, maxPostCount) =>
172
+
173
+ posts.slice(0, maxPostCount)
174
+
175
+ .reduce((obj, post) => (
176
+
177
+ {
178
+
179
+ ...obj,
180
+
181
+ [post.id]: {
182
+
183
+ ...post,
184
+
185
+ comments: comments.filter(({ postId }) => post.id === postId)
186
+
187
+ }
188
+
189
+ }
190
+
191
+ ), {});
192
+
193
+ ```
194
+
195
+ 先の(1)で挙げたコードでは、mergeの第三引数を、postIdの最大値`maxPostId`にしていましたが、postの個数の上限値`maxPostCount` に変更しました。
196
+
197
+
198
+
199
+ - **動作確認のサンプル** ???? [tera: 370866 without lodash](https://codepen.io/kilesa/pen/QWMXxxe?editors=0010) @codepen

1

テキスト追加

2021/11/24 21:51

投稿

退会済みユーザー
test CHANGED
@@ -1,3 +1,33 @@
1
+ 質問にある以下の3点
2
+
3
+
4
+
5
+ > しかし以下の点が分かりません。
6
+
7
+ ・valueには、apiから取得したkeyが対応するpostsのオブジェクトと、postsIdが一致するcommentsの配列を入れ方
8
+
9
+ ・50投稿文ループさせる方法がわからない(mapやwhileの指定が分からず)
10
+
11
+ ・JSON形式にオブジェクトを入れる方法(JSONファイルを出力するにはnode.jsを使う方法しか出てこず分からない)
12
+
13
+
14
+
15
+ のうち、はじめの2点を
16
+
17
+ (1) postsとcommentsをマージしたオブジェクトを作る
18
+
19
+ 3点目を
20
+
21
+ (2)ファイルのダウンロード方法
22
+
23
+ として回答します。
24
+
25
+
26
+
27
+ ### (1) postsとcommentsをマージしたオブジェクトを作る
28
+
29
+
30
+
1
31
  そういうときは、(まずは) [lodash](https://lodash.com/)を使って切り抜けたいです。(※ **備考**も参照ください)
2
32
 
3
33
 
@@ -85,3 +115,41 @@
85
115
 
86
116
 
87
117
  - [You don't (may not) need Lodash/Underscore](https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore) @github.com
118
+
119
+
120
+
121
+
122
+
123
+ ### (2)ファイルのダウンロード方法
124
+
125
+
126
+
127
+ マージして作成したオブジェクトをJSONファイルにしてダウンロードするには、Blobを使えばよいかと思います。たとえば、前掲の[動作確認のサンプル](https://codepen.io/kilesa/pen/ZEJdxpK?editors=0010) の中で、 Promise.all が成功したときの処理に以下を追加します。
128
+
129
+
130
+
131
+ ```diff
132
+
133
+ Promise.all(fetchers).then(([{ data: posts }, { data: comments }]) => {
134
+
135
+ const mergedPosts = merge(posts, comments, 50);
136
+
137
+ setPosts(mergedPosts);
138
+
139
+
140
+
141
+ + // ファイルとしてダウンロード
142
+
143
+ + const data = new Blob([JSON.stringify(mergedPosts, null, 4)], {type: 'application/json'});
144
+
145
+ + const link = document.createElement('a');
146
+
147
+ + link.href = window.URL.createObjectURL(data);
148
+
149
+ + link.setAttribute('download', 'mergedPosts.json');
150
+
151
+ + link.click();
152
+
153
+ });
154
+
155
+ ```