質問編集履歴

2

余計な文言削除

2020/07/08 12:02

投稿

tiiseto
tiiseto

スコア0

test CHANGED
File without changes
test CHANGED
@@ -32,16 +32,16 @@
32
32
 
33
33
  `container`はreact-reduxの`connect()`で接続されたコンポーネントという意味で話します。
34
34
 
35
+
36
+
37
+ 例えば、
38
+
39
+ `store.state`が更新されて、
40
+
41
+ Lists.js、Cards.jsが`connect()`で接続されており、それらの`mapStateToProps()`がオブジェクトを返すとします。
42
+
35
43
  <br>
36
44
 
37
- 例えば、
38
-
39
- `store.state`が更新されて、
40
-
41
- Lists.js、Cards.jsが`connect()`で接続されており、それらの`mapStateToProps()`がオブジェクトを返すとします。
42
-
43
- <br>
44
-
45
45
  その時、
46
46
 
47
47
  両者の`mapStateToProps()`がまったく同じオブジェクト内容を返すとしても、
@@ -54,19 +54,19 @@
54
54
 
55
55
  困っています。
56
56
 
57
- <br>
57
+
58
58
 
59
59
  私のreact-reduxへの理解は、`store.state`が更新されれば必ずすべての`mapStateToProps()`が実行するものと思っていました。
60
60
 
61
61
  しかしどうもこの理解を修正しなくてはいけないようです。
62
62
 
63
- <br>
63
+
64
64
 
65
65
  そこで知りたいのが、
66
66
 
67
67
  「react-reduxは、`connect()`するコンポーネントをネストの一番上だけに限定して、下位の途中に追加してはいけない仕様なのでしょうか?」ということです。
68
68
 
69
- <br>
69
+
70
70
 
71
71
  すこしネットで探してみると、ネストの途中で`connect()`しているコンポーネントを挟んでいるようなコードは見かけます。
72
72
 
@@ -74,7 +74,7 @@
74
74
 
75
75
  `store.state`が更新されたらすべての接続された`mapStateToProps()`は実行されるとあります。
76
76
 
77
- <br>
77
+
78
78
 
79
79
  この公式の文言は、別々のネスト同士の場合という前提で理解すべきでしょうか?
80
80
 
@@ -82,11 +82,11 @@
82
82
 
83
83
  やり方の問題ではあるのでしょうが、どこを修正すればいいのか見当がつきません。
84
84
 
85
- <br>
85
+
86
86
 
87
87
  どうかこのことについて詳しい方は、教えてくださいませんでしょうか。
88
88
 
89
- <br>
89
+
90
90
 
91
91
 
92
92
 
@@ -104,7 +104,7 @@
104
104
 
105
105
  エラー発生個所 : Cards.js
106
106
 
107
- <br>
107
+
108
108
 
109
109
  エラー発生理由 : Cards.jsのmapStateToProps()でstate.cardsが更新されず空オブジェクトのままで、その中身を読み取ろうとしたから。
110
110
 
@@ -690,7 +690,7 @@
690
690
 
691
691
  - ネストの上位のmapStateToProp()しか実行されないのはLists.jsやCards.jsに限定された事象なのか?
692
692
 
693
- <br>
693
+
694
694
 
695
695
  App.jsをconnect()してmapStateToProps()を定義したら、App.jsのmapStateToProps()が実行されて、Lists.jsのほうは実行されなかったので、限定された事象ではなかった。
696
696
 
@@ -698,7 +698,7 @@
698
698
 
699
699
  - store.stateは正しく更新されているのか?
700
700
 
701
- <br>
701
+
702
702
 
703
703
  loggerを定義して更新前後のstateをコンソールに出力させましたが、正しく更新されているのは確認できました。
704
704
 
@@ -706,11 +706,11 @@
706
706
 
707
707
  - 「mapStateToProps()が実行されない」の定義は?
708
708
 
709
- <br>
709
+
710
710
 
711
711
  mapStateToProps()内にconsole.log()を設けました。コンソールに出力されなかった、且つ実際にmapStateToProps()が更新されたstore.stateを受け取っていなかったとき実行されなかったと判断しています。
712
712
 
713
- <br>
713
+
714
714
 
715
715
 
716
716
 

1

同一ネストに複数コンテナがあるかどうかが問題だと認識したので質問内容を変更しました。

2020/07/08 12:02

投稿

tiiseto
tiiseto

スコア0

test CHANGED
@@ -1 +1 @@
1
- react-redux mapStateToProps()親コンポーネントでは更新されるけど、孫コンポーネントでは更新されない
1
+ react-redux ネスト下位のcontainerが持つmapStateToPropsが更新されない
test CHANGED
@@ -1,334 +1,636 @@
1
- ### 前提・実現したいこと
2
-
3
-
4
-
5
-
6
-
7
- 初めまして。
8
-
9
- reactとreduxどを使用してtrelloクローンを作成している者で
10
-
11
-
12
-
13
-
14
-
15
- 親コンポーネントでは`mapStateToProps()`が更新されるのに、孫コンポーネントでは更新されず困っています。
16
-
17
-
18
-
19
-
20
-
21
- 親コンポーネント、子コンポーネント、孫コンポーネントとある中で
22
-
23
- 親コンポーネントと孫コンポーネントが`mapStateToProps()`を使用しています。
24
-
25
-
26
-
27
-
28
-
29
- 各コンポーネントの`mapStateToProps()`が返すオブジェクトは下記のとおりです。
30
-
31
-
32
-
33
- ```
34
-
35
- /* 両者同じ内容です */
1
+ ### 実現したいこと、知りたいこと
2
+
3
+
4
+
5
+ react-redux, react-beautiful-dndを利用してtrelloクローンを作成している初心者です。
6
+
7
+
8
+
9
+ 現在、以下のようネスト構で開発始めてい
10
+
11
+ ```
12
+
13
+ App.js
14
+
15
+ └─ MainContent.js
16
+
17
+ ├─ Lists.js // container
18
+
19
+ │ └─ List.js // presentation
20
+
21
+ │ └ Cards.js // container
22
+
23
+ │ └ Card.js // presentation
24
+
25
+
26
+
27
+
28
+
29
+ └─ AddLists.js // container
30
+
31
+ ```
32
+
33
+ `container`はreact-reduxの`connect()`で接続されたコンポーネントという意味で話します。
34
+
35
+ <br>
36
+
37
+ 例えば、
38
+
39
+ `store.state`が更新されて、
40
+
41
+ Lists.js、Cards.jsが`connect()`で接続されており、それらの`mapStateToProps()`がオブジェクトを返すとします。
42
+
43
+ <br>
44
+
45
+ その時、
46
+
47
+ 両者の`mapStateToProps()`がまったく同じオブジェクト内容を返すとしても、
48
+
49
+ ネストの上位のファイルの`mapStateToProps()`しか実行されず、
50
+
51
+ 同じ内容を取得するはずの下位のファイルの`mapStateToProps()`は実行されないので
52
+
53
+ 下位のファイルでは更新された`store.state`が取得できずに
54
+
55
+ 困っています。
56
+
57
+ <br>
58
+
59
+ 私のreact-reduxへの理解は、`store.state`が更新されれば必ずすべての`mapStateToProps()`が実行するものと思っていました。
60
+
61
+ しかしどうもこの理解を修正しなくてはいけないようです。
62
+
63
+ <br>
64
+
65
+ そこで知りたいのが、
66
+
67
+ 「react-reduxは、`connect()`するコンポーネントをネストの一番上だけに限定して、下位の途中に追加してはいけない仕様なのでしょうか?」ということです。
68
+
69
+ <br>
70
+
71
+ すこしネットで探してみると、ネストの途中で`connect()`しているコンポーネントを挟んでいるようなコードは見かけます。
72
+
73
+ react-reduxの公式を見てみても、
74
+
75
+ `store.state`が更新されたらすべての接続された`mapStateToProps()`は実行されるとあります。
76
+
77
+ <br>
78
+
79
+ この公式の文言は、別々のネスト同士の場合という前提で理解すべきでしょうか?
80
+
81
+ それとも別のところに問題があるのでしょうか?
82
+
83
+ やり方の問題ではあるのでしょうが、どこを修正すればいいのか見当がつきません。
84
+
85
+ <br>
86
+
87
+ どうかこのことについて詳しい方は、教えてくださいませんでしょうか。
88
+
89
+ <br>
90
+
91
+
92
+
93
+ ### エラー内容など
94
+
95
+
96
+
97
+ エラー内容:
98
+
99
+ ```
100
+
101
+ TypeError: Cannot read property 'content' of undefined
102
+
103
+ ```
104
+
105
+ エラー発生個所 : Cards.js
106
+
107
+ <br>
108
+
109
+ エラー発生理由 : Cards.jsのmapStateToProps()でstate.cardsが更新されず空オブジェクトのままで、その中身を読み取ろうとしたから。
110
+
111
+
112
+
113
+ ```
36
114
 
37
115
  const mapStateToProps = state => {
38
116
 
39
117
  return {
40
118
 
41
- cards : state.cards,
42
-
43
- lists : state.lists,
44
-
45
- listOrder : state.listOrder
46
-
47
- };
48
-
49
- }
50
-
51
- ```
52
-
53
-
54
-
55
- `store.state.cards`がreducerによって更新されたときに、
56
-
57
- 親コンポーネント、孫コンポーネントの`mapStateToProps()`が実行されて
58
-
59
- 新たにオブジェクトを返すことを期待したのですが
60
-
61
-
62
-
63
-
64
-
65
-
66
-
67
- 親コンポーネントの`mapStateToProps()`は更新されて、
68
-
69
- どういうわけか、
70
-
71
- 孫コンポーネントの`mapStateToProps()`は実行されない
72
-
73
- という状況に陥っています。
74
-
75
-
76
-
77
-
78
-
79
- ```
119
+ cards: state.cards, // 更新されなかった
120
+
121
+ }
122
+
123
+ }
124
+
125
+ ```
126
+
127
+
128
+
129
+
130
+
131
+ ### ソースコード
132
+
133
+
134
+
135
+ - store.stateのひな型になるオブジェクト
136
+
137
+ ```JavaScript
138
+
139
+ const initialData = {
140
+
141
+
142
+
143
+ // StoreCards
144
+
145
+ cards: {
146
+
147
+
148
+
149
+ // 'card-1': { id: 'card-1', content: 'Take out the garbage' },
150
+
151
+ // 'card-2': { id: 'card-2', content: 'Wtatch my favorite show' },
152
+
153
+ // 'card-3': { id: 'card-3', content: 'Change my phone' },
154
+
155
+ // 'card-4': { id: 'card-4', content: 'Cook dinner' },
156
+
157
+ },
158
+
159
+ lists: {
160
+
161
+
162
+
163
+ // 'list-1': {
164
+
165
+ // id: 'list-1',
166
+
167
+ // title: 'add a list...',
168
+
169
+ // cardIds: ['card-1', 'card-2', 'card-3'],
170
+
171
+ // },
172
+
173
+
174
+
175
+ // 'list-2': {
176
+
177
+ // id: 'list-2',
178
+
179
+ // title: 'add a list...2',
180
+
181
+ // cardIds: ['card-4'],
182
+
183
+ // },
184
+
185
+
186
+
187
+ // 'list-3': {
188
+
189
+ // id: 'list-3',
190
+
191
+ // title: 'add a list...3',
192
+
193
+ // cardIds: ['card-5', 'card-6'],
194
+
195
+ // },
196
+
197
+ },
198
+
199
+
200
+
201
+ listOrder: [
202
+
203
+ // 'list-1', 'list-2', 'list-3'
204
+
205
+ ],
206
+
207
+ }
208
+
209
+
210
+
211
+ export default initialData;
212
+
213
+
214
+
215
+ ```
216
+
217
+
218
+
219
+ - reducer/index.js
220
+
221
+ CREATE_NEW_CARDでstateを更新したのちの話です。
222
+
223
+ ```JaVaScript
224
+
225
+ // root reducer
226
+
227
+
228
+
229
+ import * as actionTypes from '../../action_namespace';
230
+
231
+ import initialData from '../../initialData';
232
+
233
+
234
+
235
+ const initialState = { ...initialData };
236
+
237
+
238
+
239
+ const reducer = (state = initialState, action) => {
240
+
241
+
242
+
243
+ switch (action.type) {
244
+
245
+ case actionTypes.CREATE_NEW_CARD:
246
+
247
+
248
+
249
+ console.log('create new card');
250
+
251
+
252
+
253
+ if (state.listOrder.includes(action.list)) {
254
+
255
+
256
+
257
+ const newCards = { ...state.cards };
258
+
259
+ const amountOfCards = Object.keys(newCards).length;
260
+
261
+ newCards[`card-${amountOfCards + 1}`] = {
262
+
263
+ id: `card-${amountOfCards + 1}`,
264
+
265
+ content: action.content,
266
+
267
+ };
268
+
269
+
270
+
271
+ const newLists = { ...state.lists };
272
+
273
+ newLists[action.list].cardIds.push(`card-${amountOfCards + 1}`);
274
+
275
+
276
+
277
+ return {
278
+
279
+ ...state,
280
+
281
+ cards: newCards,
282
+
283
+ lists: newLists,
284
+
285
+ };
286
+
287
+
288
+
289
+ }
290
+
291
+ else {
292
+
293
+ return state;
294
+
295
+ }
296
+
297
+
298
+
299
+ default: return state;
300
+
301
+ }
302
+
303
+ }
304
+
305
+
306
+
307
+ export default reducer;
308
+
309
+ ```
310
+
311
+ - App.js
312
+
313
+ ```
314
+
315
+ import React from 'react';
316
+
317
+ import { DragDropContext } from 'react-beautiful-dnd';
318
+
319
+ import { connect } from 'react-redux';
320
+
321
+
322
+
323
+ import MainContent from './MainContent';
324
+
325
+ import classes from './App.module.css';
326
+
327
+ import { cardMoveToSameList } from '../store/action';
328
+
329
+ import * as actionTypes from '../action_namespace';
330
+
331
+
332
+
333
+ class App extends React.Component {
334
+
335
+
336
+
337
+ onDragEnd = result => {}
338
+
339
+
340
+
341
+ render() {
342
+
343
+ return (
344
+
345
+ <DragDropContext onDragEnd={this.onDragEnd}>
346
+
347
+ <div className={classes.App}>
348
+
349
+ <MainContent />
350
+
351
+ </div>
352
+
353
+ </DragDropContext>
354
+
355
+ );
356
+
357
+ }
358
+
359
+ }
360
+
361
+
362
+
363
+ export default App;
364
+
365
+
366
+
367
+ ```
368
+
369
+ - Lists.js
370
+
371
+ ```
372
+
373
+ import React from 'react';
374
+
375
+ import { connect } from 'react-redux';
376
+
377
+
378
+
379
+ import classes from './Lists.module.css';
380
+
381
+ import List from './List';
382
+
383
+
384
+
385
+ class Lists extends React.Component {
386
+
387
+
388
+
389
+ render() {
390
+
391
+ console.log(this.props);
392
+
393
+
394
+
395
+ let lists = this.props.listOrder.map(list => {
396
+
397
+ return (
398
+
399
+ <List
400
+
401
+ className={classes.Lists}
402
+
403
+ key={this.props.lists[list].id}
404
+
405
+ id={this.props.lists[list].id}
406
+
407
+ title={this.props.lists[list].title}
408
+
409
+ listName={list}
410
+
411
+ cards={this.props.cards}
412
+
413
+ />
414
+
415
+ );
416
+
417
+ });
418
+
419
+
420
+
421
+ return (
422
+
423
+ <div className={classes.Lists} >
424
+
425
+ {lists}
426
+
427
+ </div>
428
+
429
+ );
430
+
431
+ }
432
+
433
+ }
434
+
435
+
436
+
437
+
438
+
439
+ // 更新される
80
440
 
81
441
  const mapStateToProps = state => {
82
442
 
443
+
444
+
83
445
  return {
84
446
 
85
- cards : state.cards, // <-- 孫の方だけ更新されない!
447
+ cards: state.cards,
86
-
448
+
87
- lists : state.lists,
449
+ lists: state.lists,
88
-
450
+
89
- listOrder : state.listOrder
451
+ listOrder: state.listOrder
90
-
91
- };
452
+
92
-
93
- }
453
+ }
454
+
455
+ }
456
+
457
+
458
+
459
+ export default connect(mapStateToProps)(Lists);
94
460
 
95
461
  ```
96
462
 
97
-
98
-
99
- 公式でも、
100
-
101
- 接続されているすべての`mapStateToProps()`は、`store.state`の更新時に実行されるとあるのですが
102
-
103
- 私の作成しているモノでは孫コンポーネントの`mapStateToProps()`は実行されませんでした。
104
-
105
-
106
-
107
-
108
-
109
- 実現したいことは
110
-
111
- 孫コンポーネントの`mapStateToProps()`が、正しく更新された`store.state`を受け取り
112
-
113
- 孫コンポーネントに`props`として更新された値が渡され
114
-
115
- それによって孫コンポーネントが再レンダリングされることです。
116
-
117
-
118
-
119
-
120
-
121
- 想定した処理順序は、
122
-
123
- reducerが`store.state.cards`のオブジェクトに新規のオブジェクトを加えて`store.state`を更新する
124
-
125
- (正しく更新されているのは確認済)
126
-
127
-
128
-
129
- `connect()`で接続されている親コンポーネントの`mapStateToProps()`が実行される
130
-
131
- (正しく更新されているのは確認済)
132
-
133
-
134
-
135
- `connect()`で接続されている孫コンポーネントの`mapStateToProps()`が実行される
136
-
137
- (`state.cards`が更新されない)
138
-
139
-
140
-
141
- 孫コンポーネントが`mapStateToProps()`から返された正しいオブジェクトを基に再レンダリング
142
-
143
- (`state.cards`が空なのでエラー)
144
-
145
-
146
-
147
-
148
-
149
-
150
-
151
- よろしくお願いします。
152
-
153
-
154
-
155
-
156
-
157
- ### 発生している問題・エラーメッセージ
158
-
159
-
160
-
161
- #### エラーメッセージ
162
-
163
-
164
-
165
- ```
166
-
167
- /* ブラウザが吐いたエラー*/
168
-
169
- TypeError: Cannot read property 'content' of undefined
170
-
171
-
172
-
173
- /* 発生個所 */
174
-
175
- /* src/components/Cards.js */
176
-
177
- <Card
178
-
179
- key={cardId} id={cardId}
180
-
181
- content={this.props.cards[cardId].content} // ここのcontentがundefinedになってしまう。this.props.cardsが空になっているせい
182
-
183
- index={index}
184
-
185
- />
186
-
187
-
188
-
189
- ```
190
-
191
-
192
-
193
-
194
-
195
- ### 該当のソースコード
196
-
197
-
198
-
199
- ```JavaScript
200
-
201
- // store.stateの初期値として渡されるものです
202
-
203
- // コメントアウトされているような内容がreducerによって作成されます
204
-
205
- // 今回はcardsの中身が更新された後の話です
206
-
207
- const initialData = {
208
-
209
-
210
-
211
- //
212
-
213
- cards: {
214
-
215
- // 'card-1': { id: 'card-1', content: 'Take out the garbage' },
216
-
217
- // 'card-2': { id: 'card-2', content: 'Wtatch my favorite show' },
218
-
219
- // 'card-3': { id: 'card-3', content: 'Change my phone' },
220
-
221
- // 'card-4': { id: 'card-4', content: 'Cook dinner' },
222
-
223
- },
224
-
225
- lists: {
226
-
227
-
228
-
229
- // 'list-1': {
230
-
231
- // id: 'list-1',
232
-
233
- // title: 'ToDo',
234
-
235
- // cardIds: ['card-1', 'card-2', 'card-3'], // 各lists[].cardsIdを基にcardsの中から
236
-
237
- // },
238
-
239
-
240
-
241
- // 'list-2': {
242
-
243
- // id: 'list-2',
244
-
245
- // title: 'Done',
246
-
247
- // cardIds: ['card-4'],
248
-
249
- // },
250
-
251
-
252
-
253
- // 'list-3': {
254
-
255
- // id: 'list-3',
256
-
257
- // title: 'Archive',
258
-
259
- // cardIds: ['card-5', 'card-6'],
260
-
261
- // },
262
-
263
- },
264
-
265
- listOrder: [
266
-
267
- // 'list-1', 'list-2', 'list-3'
268
-
269
- ],
270
-
271
- }
272
-
273
-
274
-
275
- export default initialData;
463
+ - List.js
464
+
465
+ ```
466
+
467
+ import React from 'react';
468
+
469
+ import Cards from './Cards';
470
+
471
+ import classes from './List.module.css';
472
+
473
+
474
+
475
+ const list = props => {
476
+
477
+ return (
478
+
479
+ <div
480
+
481
+ id={props.id} className={classes.List} >
482
+
483
+ <span>{props.title}</span>
484
+
485
+ <Cards listName={props.listName} cards={props.cards} />
486
+
487
+ </div>
488
+
489
+ );
490
+
491
+ }
492
+
493
+
494
+
495
+ export default list;
276
496
 
277
497
  ```
278
498
 
279
-
280
-
281
-
282
-
283
- ```React.js
499
+ - Cards.js
284
-
500
+
285
- /* 親コンポーネント */
501
+ ```
286
-
287
-
288
502
 
289
503
  import React from 'react';
290
504
 
291
505
  import { connect } from 'react-redux';
292
506
 
507
+ import { Droppable } from 'react-beautiful-dnd';
508
+
509
+
510
+
511
+ import DroppableContainer from '../dnd/droppableContainer/droppableContainer';
512
+
293
- import classes from './Lists.module.css';
513
+ import classes from './Cards.module.css';
294
-
514
+
295
- import List from './List';
515
+ import Card from './Card';
516
+
296
-
517
+ import { createNewCard } from '../store/action';
518
+
519
+
520
+
521
+
522
+
297
-
523
+ // @props : List.jsからprops.listNameを引き継ぐ
298
-
524
+
299
- class Lists extends React.Component {
525
+ class Cards extends React.Component {
526
+
527
+
528
+
529
+ state = { inputValue: '' }
530
+
531
+
532
+
533
+ keyUpHandler = (event) => {
534
+
535
+ const ENTER_KEY = 13;
536
+
537
+ if (event.keyCode === ENTER_KEY
538
+
539
+ && this.state.inputValue !== '') {
540
+
541
+ this.props.onCreateNewCard(this.props.listName, this.state.inputValue);
542
+
543
+ this.setState({ inputValue: '' });
544
+
545
+ }
546
+
547
+ }
548
+
549
+
550
+
551
+ addCardHandler = () => {
552
+
553
+ if (this.state.inputValue !== '') {
554
+
555
+ this.props.onCreateNewCard(this.props.listName, this.state.inputValue);
556
+
557
+ this.setState({ inputValue: '' });
558
+
559
+ }
560
+
561
+ }
562
+
563
+
564
+
565
+ onChangeHandler = (event) => {
566
+
567
+ this.setState({ inputValue: event.target.value });
568
+
569
+ }
300
570
 
301
571
 
302
572
 
303
573
  render() {
304
574
 
575
+
576
+
305
- let lists = this.props.listOrder.map(list => {
577
+ // this.props.lists[].cardIdsには要素があるのに、
306
-
307
- return (
578
+
308
-
309
- <List
310
-
311
- key={this.props.lists[list].id}
312
-
313
- id={this.props.lists[list].id}
314
-
315
- title={this.props.lists[list].title}
579
+ // this.props.cardsが空オブジェクトなので、
316
-
317
- listName={list}
580
+
318
-
319
- />
581
+ // エラーが起こる
320
-
321
- );
582
+
322
-
323
- });
583
+ const cardsComp = this.props.lists[this.props.listName].cardIds.map((cardId, index) => {
324
584
 
325
585
 
326
586
 
327
587
  return (
328
588
 
589
+ <Card
590
+
591
+ key={cardId}
592
+
593
+ id={cardId}
594
+
595
+ content={this.props.cards[cardId].content} // エラー個所
596
+
597
+ index={index}
598
+
599
+ />
600
+
601
+ )
602
+
603
+ });
604
+
605
+
606
+
607
+ return (
608
+
329
- <div className={classes.Lists} >
609
+ <div className={classes.Cards}>
610
+
330
-
611
+ <Droppable droppableId={this.props.listName}>
612
+
613
+ {(provided, snapshot) => (
614
+
615
+ <DroppableContainer
616
+
617
+ innerRef={provided.innerRef}
618
+
619
+ {...provided.droppableProps}
620
+
621
+ provided={provided}
622
+
623
+ >
624
+
331
- {lists}
625
+ {cardsComp}
626
+
627
+ {provided.placeholder}
628
+
629
+ </DroppableContainer>
630
+
631
+ )}
632
+
633
+ </Droppable>
332
634
 
333
635
  </div>
334
636
 
@@ -340,202 +642,32 @@
340
642
 
341
643
 
342
644
 
645
+
646
+
647
+ // store.stateが更新されたのに更新されない
648
+
343
649
  const mapStateToProps = state => {
344
650
 
345
651
 
346
652
 
347
653
  return {
348
654
 
349
- cards: state.cards,
655
+ cards: state.cards, // state.cardsが更新されない
350
656
 
351
657
  lists: state.lists,
352
658
 
353
- listOrder: state.listOrder
659
+ listOrder: state.listOrder,
354
-
660
+
355
- }
661
+ }
356
-
662
+
357
- }
663
+ }
358
-
359
-
360
-
361
- export default connect(mapStateToProps)(Lists);
664
+
362
-
363
- ```
665
+
364
-
365
-
366
-
367
- ```React.js
666
+
368
-
369
- /*
370
-
371
- 孫コンポーネント
372
-
373
- このコンポーネントの一つ上の親コンポーネントから、
374
-
375
- listNameというpropsを受け取っています
376
-
377
- */
378
-
379
-
380
-
381
- import React from 'react';
382
-
383
- import { connect } from 'react-redux';
384
-
385
- import { Droppable } from 'react-beautiful-dnd';
386
-
387
-
388
-
389
- import DroppableContainer from '../dnd/droppableContainer/droppableContainer';
390
-
391
-
392
-
393
- import classes from './Cards.module.css';
394
-
395
- import Card from './Card';
396
-
397
- import Input from '../UI/Input';
398
-
399
- import Button from '../UI/Button';
400
-
401
- import { createNewCard } from '../store/action';
402
-
403
-
404
-
405
- class Cards extends React.Component {
406
-
407
-
408
-
409
- state = { inputValue: '' }
410
-
411
-
412
-
413
- keyUpHandler = (event) => {
414
-
415
- const ENTER_KEY = 13;
416
-
417
- if (event.keyCode === ENTER_KEY
418
-
419
- && this.state.inputValue !== '') {
420
-
421
- this.props.onCreateNewCard(this.props.listName, this.state.inputValue);
422
-
423
- this.setState({ inputValue: '' });
424
-
425
- // focus, blurとか操作したい...
426
-
427
- }
428
-
429
- }
430
-
431
-
432
-
433
- addCardHandler = () => {
434
-
435
- if (this.state.inputValue !== '') {
436
-
437
- this.props.onCreateNewCard(this.props.listName, this.state.inputValue);
438
-
439
- this.setState({ inputValue: '' });
440
-
441
- }
442
-
443
- }
444
-
445
-
446
-
447
- onChangeHandler = (event) => {
448
-
449
- this.setState({ inputValue: event.target.value });
450
-
451
- }
452
-
453
-
454
-
455
- render() {
456
-
457
-
458
-
459
- const cards = this.props.lists[this.props.listName].cardIds.map((cardId, index) => {
460
-
461
- return (
462
-
463
- <Card
464
-
465
- key={cardId}
466
-
467
- id={cardId}
468
-
469
- content={this.props.cards[cardId].content} // <-- エラー発生個所 cardsが空であるせい
470
-
471
- index={index}
472
-
473
- />
474
-
475
- )
476
-
477
- });
478
-
479
-
480
-
481
- return (
482
-
483
- <div className={classes.Cards}>
484
-
485
- <Droppable droppableId={this.props.listName}>
486
-
487
- {(provided, snapshot) => (
488
-
489
- <DroppableContainer
490
-
491
- innerRef={provided.innerRef}
492
-
493
- {...provided.droppableProps}
494
-
495
- provided={provided}
496
-
497
- >
498
-
499
- {cards}
500
-
501
- {provided.placeholder}
502
-
503
- </DroppableContainer>
504
-
505
- )}
506
-
507
- </Droppable>
508
-
509
- </div>
510
-
511
- );
512
-
513
- }
514
-
515
- }
516
-
517
-
518
-
519
- const mapStateToProps = state => {
667
+ const mapDispatchToProps = dispatch => {
520
668
 
521
669
  return {
522
670
 
523
- cards: state.cards, // <-- 更新されず空のオブジェクトのまま
524
-
525
- lists: state.lists,
526
-
527
- listOrder: state.listOrder,
528
-
529
- }
530
-
531
- }
532
-
533
-
534
-
535
- const mapDispatchToProps = dispatch => {
536
-
537
- return {
538
-
539
671
  onCreateNewCard: (list, card) => dispatch(createNewCard(list, card)),
540
672
 
541
673
  }
@@ -546,177 +678,53 @@
546
678
 
547
679
  export default connect(mapStateToProps, mapDispatchToProps)(Cards);
548
680
 
549
-
550
-
551
- ```
681
+ ```
552
-
553
-
554
-
555
- ```React.js
682
+
556
-
557
- /* 子コンポーネント */
683
+
558
-
559
- import React from 'react';
684
+
560
-
561
- import Cards from './Cards';
685
+
562
-
563
- import classes from './List.module.css';
686
+
564
-
565
-
566
-
567
- const list = props => {
568
-
569
- return (
570
-
571
- <div
572
-
573
- id={props.id} className={classes.List} >
574
-
575
- <span>{props.title}</span>
576
-
577
- <Cards listName={props.listName} />
578
-
579
- </div>
580
-
581
- );
582
-
583
- }
584
-
585
-
586
-
587
- export default list;
588
-
589
-
590
-
591
- ```
592
-
593
-
594
-
595
- ```JavaScript
596
-
597
-
598
-
599
- /* reducer */
600
-
601
-
602
-
603
- import * as actionTypes from '../../action_namespace';
604
-
605
- import initialData from '../../initialData';
606
-
607
-
608
-
609
- const initialState = { ...initialData };
610
-
611
-
612
-
613
- const reducer = (state = initialState, action) => {
614
-
615
-
616
-
617
- switch (action.type) {
618
-
619
- case actionTypes.CREATE_NEW_CARD:
620
-
621
-
622
-
623
- if (state.listOrder.includes(action.list)) {
624
-
625
-
626
-
627
- // 新しいカードを作る
628
-
629
- const newCards = { ...state.cards };
630
-
631
- // state.cardsの要素数を確認する
632
-
633
- const amountOfCards = Object.keys(newCards).length;
634
-
635
- newCards[`card-${amountOfCards + 1}`] = {
636
-
637
- id: `card-${amountOfCards + 1}`,
638
-
639
- content: action.content,
640
-
641
- };
642
-
643
-
644
-
645
-
646
-
647
- // 所属するStore.state.lists.cardIdsへ追加する
648
-
649
- const newLists = { ...state.lists };
650
-
651
- newLists[action.list].cardIds.push(`card-${amountOfCards + 1}`);
652
-
653
-
654
-
655
- return {
656
-
657
- ...state,
658
-
659
- cards: newCards,
660
-
661
- lists: newLists,
662
-
663
- };
664
-
665
-
666
-
667
- }
668
-
669
- else {
670
-
671
- return state;
672
-
673
- }
674
-
675
-
676
-
677
- default: return state;
678
-
679
- }
680
-
681
- }
682
-
683
- ```
684
-
685
-
686
-
687
-
688
-
689
- ### 試したこと
687
+ ### やってみたこと
690
-
691
-
692
-
688
+
689
+
690
+
693
- - 本当にmapStateToProps()はすべて呼び出されていないのか?
691
+ - ネストの上位のmapStateToProp()しか実行されないのはLists.jsやCards.jsに限定された事象なのか?
692
+
694
-
693
+ <br>
694
+
695
- 親、孫のmapStateToProps()へconsole.log('map state to props');に出力しましたが親の方しか呼び出されなかった。 (孫はコンソールに出力されなかった)
695
+ App.jsをconnect()してmapStateToProps()を定義したら、App.jsmapStateToProps()が実行されて、Lists.jsは実行されなかったので、限定された事象ではなかった
696
696
 
697
697
 
698
698
 
699
699
  - store.stateは正しく更新されているのか?
700
700
 
701
-
701
+ <br>
702
-
702
+
703
- store監視のloggerを設けたが正しく更新されているのは確認できました。
703
+ loggerを定義して更新前後のstateをコンソールに出力させましたが正しく更新されているのは確認できました。
704
-
705
-
706
-
707
-
708
-
709
-
710
-
711
-
712
-
713
-
714
-
704
+
705
+
706
+
715
- ### 補足情報(FW/ツールバージョンなど)
707
+ - 「mapStateToProps()が実行されない」定義は?
708
+
716
-
709
+ <br>
710
+
711
+ mapStateToProps()内にconsole.log()を設けました。コンソールに出力されなかった、且つ実際にmapStateToProps()が更新されたstore.stateを受け取っていなかったとき実行されなかったと判断しています。
712
+
713
+ <br>
714
+
715
+
716
+
717
+ ### 補足情報
718
+
719
+
720
+
721
+ package.json
722
+
717
- ```
723
+ ```
724
+
718
-
725
+ {
726
+
719
- package.json{
727
+ "dependencies": {
720
728
 
721
729
  "react": "^16.13.1",
722
730
 
@@ -730,6 +738,6 @@
730
738
 
731
739
  "redux": "^4.0.5"
732
740
 
733
- }
741
+ },
734
-
742
+
735
- ```
743
+ ```