回答編集履歴

14

テキスト修正

2019/01/18 06:25

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -366,7 +366,19 @@
366
366
 
367
367
 
368
368
 
369
+ コメントから頂きました、
370
+
371
+
372
+
373
+ > hfidk 2019/01/17 18:13
374
+
375
+ >
376
+
377
+ 余計な質問すいません,追加するタグの名前をオブジェクトのキー名にすることってできませんか?
378
+
379
+
380
+
369
- 以下の質問と同じ要望かと思います。
381
+ とのご質問への回答です。これは以下の質問と同じ要望かと思います。
370
382
 
371
383
 
372
384
 

13

テキスト修正

2019/01/18 06:25

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -498,7 +498,7 @@
498
498
 
499
499
 
500
500
 
501
- キーとなる文字列とコンポーネントをマップするオブジェクト `tagComponents` を作るというのが、ひと手間かかりますが、いったんルールを決めて作ってしまえば、追加していくのはそれほど大変ではありません。私自身、時々、業務でも使います。
501
+ キーとなる文字列とコンポーネントをマップするオブジェクト `tagComponents` を作るというのが、ひと手間かかりますが、いったんルールを決めて作ってしまえば、追加していくのはそれほど大変ではありません。私自身、時々、業務でも使う小技です。
502
502
 
503
503
 
504
504
 

12

テキスト修正

2019/01/17 10:38

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -518,4 +518,4 @@
518
518
 
519
519
  ```
520
520
 
521
- としてまって、 `<tag />` と書いても意図したようには表示されません。
521
+ として `<tag />` と書いても意図したようには表示されません。

11

テキスト修正

2019/01/17 10:33

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -359,3 +359,163 @@
359
359
  }
360
360
 
361
361
  ```
362
+
363
+
364
+
365
+ ### 追記4
366
+
367
+
368
+
369
+ 以下の質問と同じ要望かと思います。
370
+
371
+
372
+
373
+ - stackoverflow: [Create an instance of a React class from a string](https://stackoverflow.com/questions/30172433/create-an-instance-of-a-react-class-from-a-string)
374
+
375
+
376
+
377
+ 上記への回答、
378
+
379
+ - [https://stackoverflow.com/a/30172587/4643029](https://stackoverflow.com/a/30172587/4643029)
380
+
381
+
382
+
383
+ にある
384
+
385
+
386
+
387
+ > So you simply need to find a way to map between the string "Home" and the component class Home. A simple object will work as a basic registry, and you can build from there if you need more features.
388
+
389
+
390
+
391
+ ```javascript
392
+
393
+ var components = {
394
+
395
+ "Home": Home,
396
+
397
+ "Other": OtherComponent
398
+
399
+ };
400
+
401
+
402
+
403
+ var Component = components[this.props.template];
404
+
405
+ ```
406
+
407
+
408
+
409
+
410
+
411
+ を参考にすればよいです。以下簡単なサンプルです。
412
+
413
+
414
+
415
+ 3つのタグコンポーネント `FooTag`, `BarTag`, `BazTag` があります。`App` のprops `tag` に `"foo"`,`"bar"`,`"baz"` のいずれかが渡ってくる想定で、これらの文字列から表示対象のタグコンポーネントを変数 `Tag` に入れて、これをJSX形式で書いて表示するという例です。
416
+
417
+
418
+
419
+ ```jsx
420
+
421
+ class FooTag extends React.Component {
422
+
423
+ render() {
424
+
425
+ return <span>This is a FooTag.</span>;
426
+
427
+ }
428
+
429
+ }
430
+
431
+
432
+
433
+ class BarTag extends React.Component {
434
+
435
+ render() {
436
+
437
+ return <span>This is a BarTag.</span>;
438
+
439
+ }
440
+
441
+ }
442
+
443
+
444
+
445
+ class BazTag extends React.Component {
446
+
447
+ render() {
448
+
449
+ return <span>This is a BazTag.</span>;
450
+
451
+ }
452
+
453
+ }
454
+
455
+
456
+
457
+ const tagComponents = {
458
+
459
+ foo: FooTag,
460
+
461
+ bar: BarTag,
462
+
463
+ baz: BazTag,
464
+
465
+ };
466
+
467
+
468
+
469
+ class App extends React.Component {
470
+
471
+ render() {
472
+
473
+ const Tag = tagComponents[this.props.tag] || FooTag;
474
+
475
+ return (
476
+
477
+ <div className="app">
478
+
479
+ <Tag />
480
+
481
+ </div>
482
+
483
+ );
484
+
485
+ }
486
+
487
+ }
488
+
489
+
490
+
491
+ ReactDOM.render(<App tag="bar" />, document.querySelector("#app"));
492
+
493
+ ```
494
+
495
+ - 動作確認用サンプル: [https://jsfiddle.net/jun68ykt/0zc3L7ke/7/](https://jsfiddle.net/jun68ykt/0zc3L7ke/7/)
496
+
497
+
498
+
499
+
500
+
501
+ キーとなる文字列とコンポーネントをマップするオブジェクト `tagComponents` を作るというのが、ひと手間かかりますが、いったんルールを決めて作ってしまえば、追加していくのはそれほど大変ではありません。私自身、時々、業務でも使います。
502
+
503
+
504
+
505
+ 肝は、
506
+
507
+ ```javascript
508
+
509
+ const Tag = tagComponents[this.props.tag] || FooTag;
510
+
511
+ ```
512
+
513
+ と、`Tag`のような、大文字で始まる変数名に代入することです。こうすると `<Tag />` と書けますが、これを
514
+
515
+ ```javascript
516
+
517
+ const tag = tagComponents[this.props.tag] || FooTag;
518
+
519
+ ```
520
+
521
+ としてまって、 `<tag />` と書いても意図したようには表示されません。

10

テキスト修正

2019/01/17 10:11

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -282,7 +282,7 @@
282
282
 
283
283
 
284
284
 
285
- 上記を以下のように修正してみるといかがでしょうか? (こんどは`push`で大丈夫です。)
285
+ これだと、`components_Data` に複数タグ分のデータがあったときに、setStateが複数回呼ばれてしまいます。ですので、上記を以下のように修正してみるといかがでしょうか? (こんどは`push`で大丈夫です。)
286
286
 
287
287
 
288
288
 
@@ -320,7 +320,7 @@
320
320
 
321
321
  `this.setState({ drawnTag });`
322
322
 
323
- で、state に反映させるようにして、 `getInfo`が呼ばれたときに `setState` が1回だけ実行されるようにます。
323
+ で、state に反映させるようにします。こうすることで`getInfo`が呼ばれたときに `setState` が1回だけ実行されるようになります。
324
324
 
325
325
 
326
326
 

9

テキスト修正

2019/01/17 02:32

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -239,3 +239,123 @@
239
239
 
240
240
 
241
241
  その上で Clock を使う側では `<Clock view="horizontal" />` または `<Clock view="vertical" />` というように、適切な値の`view`をpropsで渡すようにすればよいかと思います。逆に、表示したときにスタイルがあたらずに時と分が表示されたら、それは `view`の値が適切にprops経由で渡せていないと気がつくことができます。
242
+
243
+
244
+
245
+
246
+
247
+ ### 追記3
248
+
249
+
250
+
251
+ ご質問にあるコードの以下の部分で、 `forEach` の中で setState しているのが怪しいです。
252
+
253
+
254
+
255
+ **修正前:**
256
+
257
+ ```
258
+
259
+ getInfo = () =>{
260
+
261
+ var ref_Data = require('../users_mirror.json');
262
+
263
+ var components_Data = ref_Data.users[this.props.account_Name].components;
264
+
265
+ Object.keys(components_Data).forEach(function(key){
266
+
267
+ if(components_Data[key]){
268
+
269
+ this.setState({
270
+
271
+ drawnTag: this.state.drawnTag.push(<Comp />)
272
+
273
+ });
274
+
275
+ }
276
+
277
+ }.bind(this));
278
+
279
+ }
280
+
281
+ ```
282
+
283
+
284
+
285
+ 上記を以下のように修正してみるといかがでしょうか? (こんどは`push`で大丈夫です。)
286
+
287
+
288
+
289
+ **修正後:**
290
+
291
+ ```javascript
292
+
293
+ getInfo = () =>{
294
+
295
+ var ref_Data = require('../users_mirror.json');
296
+
297
+ var components_Data = ref_Data.users[this.props.account_Name].components;
298
+
299
+ var drawnTag = [];
300
+
301
+ Object.keys(components_Data).forEach(function(key){
302
+
303
+ if(components_Data[key]){
304
+
305
+ drawnTag.push(<Comp />);
306
+
307
+ }
308
+
309
+ });
310
+
311
+ this.setState({ drawnTag });
312
+
313
+ };
314
+
315
+ ```
316
+
317
+
318
+
319
+ すなわち、 `forEach` のループに入る前に、 `drawnTag` というローカル変数で空配列の配列を用意しておき、 `forEach` のループでこの配列に `<Comp />` を追加していきます。そして、`forEach`を抜けた後に、
320
+
321
+ `this.setState({ drawnTag });`
322
+
323
+ で、state に反映させるようにして、 `getInfo`が呼ばれたときに `setState` が1回だけ実行されるようにします。
324
+
325
+
326
+
327
+ 上記の趣旨の修正をお手元のコードにしてみると意図通り動くかもしれません。
328
+
329
+
330
+
331
+ それと、 `console.log(this.state.drawnTag);` というデバッグログは、以下のように render の中で行うのがよいです。一度、他の箇所にある`console.log(this.state.drawnTag);` をコメントアウトして、以下の箇所にだけ入れてみることをお勧めします。
332
+
333
+
334
+
335
+ ```javascript
336
+
337
+ render() {
338
+
339
+ console.log(this.state.drawnTag);
340
+
341
+ return (
342
+
343
+ <div>
344
+
345
+ {this.state.drawnTag.map((item, i) =>
346
+
347
+ <React.Fragment key={i}>
348
+
349
+ <div>{item}</div>
350
+
351
+ </React.Fragment>)
352
+
353
+ }
354
+
355
+ </div>
356
+
357
+ );
358
+
359
+ }
360
+
361
+ ```

8

テキスト修正

2019/01/17 02:15

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -144,6 +144,18 @@
144
144
 
145
145
   
146
146
 
147
+ 修正方法ですが、`render()` の終わりの `}` の直前に
148
+
149
+ ```javascript
150
+
151
+ return <div>{this.state.hours}{this.state.minutes}</div>;
152
+
153
+ ```
154
+
155
+ を追加して、 以下のようにします。 
156
+
157
+  
158
+
147
159
  **修正後:**
148
160
 
149
161
  ```jsx
@@ -218,19 +230,7 @@
218
230
 
219
231
 
220
232
 
221
- 上記のように、 `render()` の終わ `}` の直前
222
-
223
- ```javascript
224
-
225
- return <div>{this.state.hours}{this.state.minutes}</div>;
226
-
227
- ```
228
-
229
- を追加して、 `Clock` の props `view` が与えられなかったり、与えられても`horizontal`または`vertical`のいずれでもない場合に、とりあえず`{this.state.hours}`と`{this.state.minutes}`を並べて、 classNameやstyleを指定しない単なる `<div>`で囲んだものを返すようにしておきます。
230
-
231
-
232
-
233
- このようにしておけば、Clock を使う側で `<Clock />` のように `view`を指定し忘れても、
233
+ のように修正すると`Clock` の props `view` が与えられなかったり、与えられても`horizontal`または`vertical`のいずれでもない場合に、とりあえず`{this.state.hours}`と`{this.state.minutes}`を並べて、 classNameやstyleを指定しない単なる `<div>`で囲んだもを返すようにな、Clock を使う側で `<Clock />` のよう`view`を指定し忘れても、
234
234
 
235
235
  `"Nothing was returned from render." `
236
236
 

7

テキスト修正

2019/01/16 05:49

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -226,12 +226,16 @@
226
226
 
227
227
  ```
228
228
 
229
- を追加して、 `Clock` の props `view` が与えられなかったり、与えられても`horizontal`または`vertical`のいずれでもない場合に、とりあえず何もスタイルをあてないで、`{this.state.hours}`と`{this.state.minutes}`を並べて `<div>`で囲んだものを返すようにしておきます。
229
+ を追加して、 `Clock` の props `view` が与えられなかったり、与えられても`horizontal`または`vertical`のいずれでもない場合に、とりあえず`{this.state.hours}`と`{this.state.minutes}`を並べて classNameやstyleを指定しない単なる `<div>`で囲んだものを返すようにしておきます。
230
-
231
-
232
-
230
+
231
+
232
+
233
- とりあえず上記のようにしておけば、Clock を使う側で `<Clock />` のように `view`を指定し忘れても、`"Nothing was returned from render." ` は出なくなると思います。
233
+ のようにしておけば、Clock を使う側で `<Clock />` のように `view`を指定し忘れても、
234
+
234
-
235
+ `"Nothing was returned from render." `
236
+
235
-
237
+ は出なくなると思います。
236
-
238
+
239
+
240
+
237
- その上で Clock を使う側では `<Clock view="horizontal" />` または `<Clock view="vertical" />` というように、適切な値の`view`をpropsで渡すようにすればよいかと思います。スタイルがあたらずに時と分が表示されたら、それは `view`の値が適切にprops経由で渡せていないと気がつくことができます。
241
+ その上で Clock を使う側では `<Clock view="horizontal" />` または `<Clock view="vertical" />` というように、適切な値の`view`をpropsで渡すようにすればよいかと思います。逆に、表示したときにスタイルがあたらずに時と分が表示されたら、それは `view`の値が適切にprops経由で渡せていないと気がつくことができます。

6

テキスト修正

2019/01/16 04:58

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -234,4 +234,4 @@
234
234
 
235
235
 
236
236
 
237
- その上でClock を使う側では `<Clock view="horizontal" />` または `<Clock view="vertical" />` というように、`view`をpropsで渡すようにすればよいかと思います。スタイルがあたらずに時と分が表示されたら、それは `view`の値が適切にprops経由で渡せていないと気がつくことができます。
237
+ その上で Clock を使う側では `<Clock view="horizontal" />` または `<Clock view="vertical" />` というように、適切な値の`view`をpropsで渡すようにすればよいかと思います。スタイルがあたらずに時と分が表示されたら、それは `view`の値が適切にprops経由で渡せていないと気がつくことができます。

5

テキスト修正

2019/01/16 04:43

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -218,7 +218,15 @@
218
218
 
219
219
 
220
220
 
221
- 上記のように、 `render()` の終わりの `}` の直前に `return <div>{this.state.hours}{this.state.minutes}</div>;` を追加して、 `Clock` の props `view` が与えられなかったり、与えられても`horizontal`または`vertical`のいずれでもない場合に、とりあえず何もスタイルをあてないで、`{this.state.hours}`と`{this.state.minutes}`を並べて `<div>`で囲んだものを返すようにしておきます。
221
+ 上記のように、 `render()` の終わりの `}` の直前に
222
+
223
+ ```javascript
224
+
225
+ return <div>{this.state.hours}{this.state.minutes}</div>;
226
+
227
+ ```
228
+
229
+ を追加して、 `Clock` の props `view` が与えられなかったり、与えられても`horizontal`または`vertical`のいずれでもない場合に、とりあえず何もスタイルをあてないで、`{this.state.hours}`と`{this.state.minutes}`を並べて `<div>`で囲んだものを返すようにしておきます。
222
230
 
223
231
 
224
232
 

4

テキスト修正

2019/01/16 04:41

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -206,19 +206,19 @@
206
206
 
207
207
  );
208
208
 
209
- } else {
210
-
211
- return <div>{this.state.hours}{this.state.minutes}</div>;
212
-
213
209
  }
214
210
 
211
+
212
+
213
+ return <div>{this.state.hours}{this.state.minutes}</div>; // この行を追加
214
+
215
215
  }
216
216
 
217
217
  ```
218
218
 
219
219
 
220
220
 
221
- 上記のように、 `else { return <div>{this.state.hours}{this.state.minutes}</div>; }` を追加して、 `Clock` の props `view` が与えられなかったり、与えられても`horizontal`または`vertical`のいずれでもない場合に、とりあえず何もスタイルをあてないで、`{this.state.hours}`と`{this.state.minutes}`を並べて `<div>`で囲んだものを返すようにしておきます。
221
+ 上記のように、 `render()` の終わりの `}` の直前に `return <div>{this.state.hours}{this.state.minutes}</div>;` を追加して、 `Clock` の props `view` が与えられなかったり、与えられても`horizontal`または`vertical`のいずれでもない場合に、とりあえず何もスタイルをあてないで、`{this.state.hours}`と`{this.state.minutes}`を並べて `<div>`で囲んだものを返すようにしておきます。
222
222
 
223
223
 
224
224
 

3

テキスト修正

2019/01/16 03:11

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -54,8 +54,176 @@
54
54
 
55
55
 
56
56
 
57
- ### 補足
57
+ ### 追記1
58
58
 
59
59
 
60
60
 
61
61
  componentWillMount は [React 16.3から非推奨メソッドになった](https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path)ので、v16.3以降を使用の際は、替わりに componentDidMount を使うことをお勧めします。
62
+
63
+
64
+
65
+ ### 追記2
66
+
67
+
68
+
69
+ `Clock` の `render` で発生している `"Nothing was returned from render." ` というエラーは、以下の修正でとりあえず発生しなくなると思います。
70
+
71
+
72
+
73
+ **修正前:**
74
+
75
+ ```jsx
76
+
77
+ render() { //デジタル時計のデザインをpropsで管理できるようにした."view=''"で"vertical"で水平に"horizontal"で縦並びに
78
+
79
+ if (this.props.view === "horizontal") {
80
+
81
+ return (
82
+
83
+ <div
84
+
85
+ style={{}}
86
+
87
+ className="clock_flame"
88
+
89
+ >
90
+
91
+ <span id="clock_hour">
92
+
93
+ {this.state.hours}
94
+
95
+ </span>
96
+
97
+ <span id="clock_minute">
98
+
99
+ {this.state.minutes}
100
+
101
+ </span>
102
+
103
+ </div>
104
+
105
+ )
106
+
107
+ } else if (this.props.view === "vertical") {
108
+
109
+ return (
110
+
111
+ <div
112
+
113
+ style={{}}
114
+
115
+ className="clock_flame_vertical"
116
+
117
+ >
118
+
119
+ <div id="clock_hour_vertical" className="vertical">
120
+
121
+ {this.state.hours}
122
+
123
+ </div>
124
+
125
+ <div id="clock_minute_vertical" className="vertical">
126
+
127
+ {this.state.minutes}
128
+
129
+ </div>
130
+
131
+ </div>
132
+
133
+ );
134
+
135
+ }
136
+
137
+ }
138
+
139
+ ```
140
+
141
+  
142
+
143
+  
144
+
145
+  
146
+
147
+ **修正後:**
148
+
149
+ ```jsx
150
+
151
+ render() { //デジタル時計のデザインをpropsで管理できるようにした."view=''"で"vertical"で水平に"horizontal"で縦並びに
152
+
153
+ if (this.props.view === "horizontal") {
154
+
155
+ return (
156
+
157
+ <div
158
+
159
+ style={{}}
160
+
161
+ className="clock_flame"
162
+
163
+ >
164
+
165
+ <span id="clock_hour">
166
+
167
+ {this.state.hours}
168
+
169
+ </span>
170
+
171
+ <span id="clock_minute">
172
+
173
+ {this.state.minutes}
174
+
175
+ </span>
176
+
177
+ </div>
178
+
179
+ )
180
+
181
+ } else if (this.props.view === "vertical") {
182
+
183
+ return (
184
+
185
+ <div
186
+
187
+ style={{}}
188
+
189
+ className="clock_flame_vertical"
190
+
191
+ >
192
+
193
+ <div id="clock_hour_vertical" className="vertical">
194
+
195
+ {this.state.hours}
196
+
197
+ </div>
198
+
199
+ <div id="clock_minute_vertical" className="vertical">
200
+
201
+ {this.state.minutes}
202
+
203
+ </div>
204
+
205
+ </div>
206
+
207
+ );
208
+
209
+ } else {
210
+
211
+ return <div>{this.state.hours}{this.state.minutes}</div>;
212
+
213
+ }
214
+
215
+ }
216
+
217
+ ```
218
+
219
+
220
+
221
+ 上記のように、 `else { return <div>{this.state.hours}{this.state.minutes}</div>; }` を追加して、 `Clock` の props `view` が与えられなかったり、与えられても`horizontal`または`vertical`のいずれでもない場合に、とりあえず何もスタイルをあてないで、`{this.state.hours}`と`{this.state.minutes}`を並べて `<div>`で囲んだものを返すようにしておきます。
222
+
223
+
224
+
225
+ とりあえず上記のようにしておけば、Clock を使う側で `<Clock />` のように `view`を指定し忘れても、`"Nothing was returned from render." ` は出なくなると思います。
226
+
227
+
228
+
229
+ その上で、Clock を使う側では `<Clock view="horizontal" />` または `<Clock view="vertical" />` というように、`view`をpropsで渡すようにすればよいかと思います。スタイルがあたらずに時と分が表示されたら、それは `view`の値が適切にprops経由で渡せていないと気がつくことができます。

2

テキスト修正

2019/01/16 02:06

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -58,4 +58,4 @@
58
58
 
59
59
 
60
60
 
61
- componentWillMount は [React 16.3から非推奨メソッドになった](https://medium.com/@baphemot/whats-new-in-react-16-3-d2c9b7b6193b)ので、v16.3以降を使用の際は、替わりに componentDidMount を使うことをお勧めします。
61
+ componentWillMount は [React 16.3から非推奨メソッドになった](https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path)ので、v16.3以降を使用の際は、替わりに componentDidMount を使うことをお勧めします。

1

テキスト修正

2019/01/15 02:32

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -51,3 +51,11 @@
51
51
 
52
52
 
53
53
  以上参考になれば幸いです。
54
+
55
+
56
+
57
+ ### 補足
58
+
59
+
60
+
61
+ componentWillMount は [React 16.3から非推奨メソッドになった](https://medium.com/@baphemot/whats-new-in-react-16-3-d2c9b7b6193b)ので、v16.3以降を使用の際は、替わりに componentDidMount を使うことをお勧めします。