質問編集履歴
2
追記
test
CHANGED
File without changes
|
test
CHANGED
@@ -354,165 +354,11 @@
|
|
354
354
|
|
355
355
|
return (
|
356
356
|
|
357
|
-
<div className={styles.post}>
|
358
|
-
|
359
|
-
<div className={styles.post_avatar}>
|
360
|
-
|
361
|
-
<Avatar
|
362
|
-
|
363
|
-
src={props.avatar}
|
364
|
-
|
365
|
-
className={styles.hoverAvatar}
|
366
|
-
|
367
|
-
onClick={() => props.updateProfile(props.username, props.avatar)}/>
|
368
|
-
|
369
|
-
</div>
|
370
|
-
|
371
|
-
<div className={styles.post_body}>
|
372
|
-
|
373
|
-
<div>
|
374
|
-
|
375
|
-
<div className={styles.post_header}>
|
376
|
-
|
377
|
-
<h3>
|
378
|
-
|
379
|
-
<span
|
380
|
-
|
381
|
-
className={styles.post_headerUser}
|
382
|
-
|
383
|
-
onClick={() => props.updateProfile(props.username, props.avatar)}
|
384
|
-
|
385
|
-
>@{props.username}</span>
|
386
|
-
|
387
|
-
<span className={styles.post_headerTime}>
|
388
|
-
|
389
|
-
{new Date(props.timestamp?.toDate()).toLocaleString()}
|
390
|
-
|
391
|
-
</span>
|
392
|
-
|
393
|
-
</h3>
|
394
|
-
|
395
|
-
</div>
|
396
|
-
|
397
|
-
<div className={styles.post_tweet}>
|
398
|
-
|
399
|
-
{props.trainingArray.map((record: any, index: number) => (
|
400
|
-
|
401
|
-
<p key={index} className="text-lg text-white font-bold">{record.trainingName} {record.trainingWeight}✖︎{record.trainingReps}回</p>
|
402
|
-
|
403
|
-
))}
|
404
|
-
|
405
|
-
</div>
|
406
|
-
|
407
|
-
</div>
|
408
|
-
|
409
|
-
{props.image && (
|
410
|
-
|
411
|
-
<div className={styles.post_tweetImage}>
|
412
|
-
|
413
|
-
<img src={props.image} alt="tweet" />
|
414
|
-
|
415
|
-
</div>
|
416
|
-
|
417
|
-
)}
|
418
|
-
|
419
|
-
<MessageIcon
|
420
|
-
|
421
|
-
className={styles.post_commentIcon}
|
422
|
-
|
423
|
-
onClick={() => setOpenComments(!openComments)}
|
424
|
-
|
425
|
-
/>
|
426
|
-
|
427
|
-
|
357
|
+
.
|
428
|
-
|
429
|
-
|
358
|
+
|
430
|
-
|
431
|
-
<DeleteIcon
|
432
|
-
|
433
|
-
className={styles.post_deleteIcon}
|
434
|
-
|
435
|
-
onClick={deletePost}
|
436
|
-
|
437
|
-
/>
|
438
|
-
|
439
|
-
|
359
|
+
.
|
440
|
-
|
441
|
-
|
360
|
+
|
442
|
-
|
443
|
-
<>
|
444
|
-
|
445
|
-
|
361
|
+
.
|
446
|
-
|
447
|
-
comments.map((com) => (
|
448
|
-
|
449
|
-
<div key={com.id} className={styles.post_comment}>
|
450
|
-
|
451
|
-
<Avatar src={com.avatar} className={classes.small}/>
|
452
|
-
|
453
|
-
<span className={styles.post_commentUser}>@{com.username}</span>
|
454
|
-
|
455
|
-
<span className={styles.post_commentText}>{com.text}</span>
|
456
|
-
|
457
|
-
<span className={styles.post_headerTime}>{new Date(com.timestamp?.toDate()).toLocaleString()}</span>
|
458
|
-
|
459
|
-
</div>
|
460
|
-
|
461
|
-
))
|
462
|
-
|
463
|
-
}
|
464
|
-
|
465
|
-
<form onSubmit={newComment}>
|
466
|
-
|
467
|
-
<div className={styles.post_form}>
|
468
|
-
|
469
|
-
<input
|
470
|
-
|
471
|
-
className={styles.post_input}
|
472
|
-
|
473
|
-
type="text"
|
474
|
-
|
475
|
-
placeholder="Type new comment..."
|
476
|
-
|
477
|
-
value={comment}
|
478
|
-
|
479
|
-
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
480
|
-
|
481
|
-
setComment(e.target.value)
|
482
|
-
|
483
|
-
}}
|
484
|
-
|
485
|
-
/>
|
486
|
-
|
487
|
-
<button
|
488
|
-
|
489
|
-
type="submit"
|
490
|
-
|
491
|
-
disabled={!comment}
|
492
|
-
|
493
|
-
className={
|
494
|
-
|
495
|
-
comment ? styles.post_button : styles.post_buttonDisable
|
496
|
-
|
497
|
-
}
|
498
|
-
|
499
|
-
>
|
500
|
-
|
501
|
-
<SendIcon className={styles.post_sendIcon} />
|
502
|
-
|
503
|
-
</button>
|
504
|
-
|
505
|
-
</div>
|
506
|
-
|
507
|
-
</form>
|
508
|
-
|
509
|
-
</>
|
510
|
-
|
511
|
-
)}
|
512
|
-
|
513
|
-
</div>
|
514
|
-
|
515
|
-
</div>
|
516
362
|
|
517
363
|
)
|
518
364
|
|
@@ -524,4 +370,156 @@
|
|
524
370
|
|
525
371
|
```
|
526
372
|
|
373
|
+
```FeedTSX
|
374
|
+
|
375
|
+
import React, { useState, useEffect } from 'react'
|
376
|
+
|
377
|
+
import styles from './Feed.module.css';
|
378
|
+
|
379
|
+
import { db } from "../firebase";
|
380
|
+
|
381
|
+
import TrainingInput from './TrainingInput';
|
382
|
+
|
383
|
+
import Post from './Post';
|
384
|
+
|
385
|
+
import User from './User';
|
386
|
+
|
387
|
+
import { selectUser } from "../features/userSlice";
|
388
|
+
|
389
|
+
import { useSelector } from "react-redux";
|
390
|
+
|
391
|
+
interface User {
|
392
|
+
|
393
|
+
profileUserName: string;
|
394
|
+
|
395
|
+
avatar: string;
|
396
|
+
|
397
|
+
}
|
398
|
+
|
399
|
+
interface Post {
|
400
|
+
|
401
|
+
id: string;
|
402
|
+
|
403
|
+
avatar: string;
|
404
|
+
|
405
|
+
image: string;
|
406
|
+
|
407
|
+
trainingArray: [];
|
408
|
+
|
409
|
+
timestamp: any;
|
410
|
+
|
411
|
+
username: string;
|
412
|
+
|
413
|
+
uid: string;
|
414
|
+
|
415
|
+
}
|
416
|
+
|
417
|
+
const Feed: React.FC = () => {
|
418
|
+
|
419
|
+
const [ posts, setPosts] = useState<Post[]>([{
|
420
|
+
|
421
|
+
id: "",
|
422
|
+
|
423
|
+
avatar: "",
|
424
|
+
|
425
|
+
image: "",
|
426
|
+
|
427
|
+
trainingArray: [],
|
428
|
+
|
429
|
+
timestamp: null,
|
430
|
+
|
431
|
+
username: "",
|
432
|
+
|
433
|
+
uid: "",
|
434
|
+
|
435
|
+
},
|
436
|
+
|
437
|
+
]);
|
438
|
+
|
439
|
+
const user = useSelector(selectUser);
|
440
|
+
|
441
|
+
const [profileUser, setProfileUser ] = useState<User>({
|
442
|
+
|
443
|
+
profileUserName: user.displayName,
|
444
|
+
|
445
|
+
avatar: user.photoUrl
|
446
|
+
|
447
|
+
}
|
448
|
+
|
449
|
+
)
|
450
|
+
|
451
|
+
// データベースから投稿一覧を取得してstateに入れる
|
452
|
+
|
453
|
+
useEffect(() => {
|
454
|
+
|
455
|
+
const unSub = db
|
456
|
+
|
457
|
+
.collection("training_posts")
|
458
|
+
|
459
|
+
.orderBy("timestamp", "desc")
|
460
|
+
|
461
|
+
.onSnapshot((snapshot) => setPosts(
|
462
|
+
|
463
|
+
snapshot.docs.map((doc) => ({
|
464
|
+
|
465
|
+
id: doc.id,
|
466
|
+
|
467
|
+
avatar: doc.data().avatar,
|
468
|
+
|
469
|
+
image: doc.data().image,
|
470
|
+
|
471
|
+
trainingArray: doc.data().training_array,
|
472
|
+
|
473
|
+
timestamp: doc.data().timestamp,
|
474
|
+
|
475
|
+
username: doc.data().username,
|
476
|
+
|
477
|
+
uid: doc.data().uid
|
478
|
+
|
479
|
+
}))
|
480
|
+
|
481
|
+
));
|
482
|
+
|
483
|
+
return () => {
|
484
|
+
|
485
|
+
unSub();
|
486
|
+
|
487
|
+
};
|
488
|
+
|
489
|
+
}, []);
|
490
|
+
|
491
|
+
//ユーザープロフィール画面の表示をユーザーごとに切り替える
|
492
|
+
|
493
|
+
const updateProfile = (name:string, avatar:string) => {
|
494
|
+
|
495
|
+
console.log(`${name} + ${avatar}`);
|
496
|
+
|
497
|
+
setProfileUser({
|
498
|
+
|
499
|
+
profileUserName: name,
|
500
|
+
|
501
|
+
avatar: avatar,
|
502
|
+
|
503
|
+
})
|
504
|
+
|
505
|
+
}
|
506
|
+
|
507
|
+
return (
|
508
|
+
|
509
|
+
.
|
510
|
+
|
511
|
+
.
|
512
|
+
|
513
|
+
.
|
514
|
+
|
515
|
+
);
|
516
|
+
|
517
|
+
}
|
518
|
+
|
519
|
+
export default Feed
|
520
|
+
|
521
|
+
|
522
|
+
|
523
|
+
```
|
524
|
+
|
527
525
|
原因がわかりましたら、教えていただきたいです。
|
1
追記
test
CHANGED
File without changes
|
test
CHANGED
@@ -72,6 +72,94 @@
|
|
72
72
|
|
73
73
|
```
|
74
74
|
|
75
|
+
Post.tsxへは、親のFeed.tsxからpropsを渡しています。
|
76
|
+
|
77
|
+
```FeedTSX
|
78
|
+
|
79
|
+
{posts.length &&
|
80
|
+
|
81
|
+
<>
|
82
|
+
|
83
|
+
{posts.map((post) => (
|
84
|
+
|
85
|
+
<Post
|
86
|
+
|
87
|
+
key={post.id}
|
88
|
+
|
89
|
+
postId={post.id}
|
90
|
+
|
91
|
+
avatar={post.avatar}
|
92
|
+
|
93
|
+
image={post.image}
|
94
|
+
|
95
|
+
trainingArray={post.trainingArray}
|
96
|
+
|
97
|
+
timestamp={post.timestamp}
|
98
|
+
|
99
|
+
username={post.username}
|
100
|
+
|
101
|
+
postUid={post.uid}
|
102
|
+
|
103
|
+
updateProfile={updateProfile}
|
104
|
+
|
105
|
+
/>
|
106
|
+
|
107
|
+
))}
|
108
|
+
|
109
|
+
</>
|
110
|
+
|
111
|
+
}
|
112
|
+
|
113
|
+
```
|
114
|
+
|
115
|
+
```FeedTSX
|
116
|
+
|
117
|
+
// データベースから投稿一覧を取得してstateに入れる
|
118
|
+
|
119
|
+
useEffect(() => {
|
120
|
+
|
121
|
+
const unSub = db
|
122
|
+
|
123
|
+
.collection("training_posts")
|
124
|
+
|
125
|
+
.orderBy("timestamp", "desc")
|
126
|
+
|
127
|
+
.onSnapshot((snapshot) => setPosts(
|
128
|
+
|
129
|
+
snapshot.docs.map((doc) => ({
|
130
|
+
|
131
|
+
id: doc.id,
|
132
|
+
|
133
|
+
avatar: doc.data().avatar,
|
134
|
+
|
135
|
+
image: doc.data().image,
|
136
|
+
|
137
|
+
trainingArray: doc.data().training_array,
|
138
|
+
|
139
|
+
timestamp: doc.data().timestamp,
|
140
|
+
|
141
|
+
username: doc.data().username,
|
142
|
+
|
143
|
+
uid: doc.data().uid
|
144
|
+
|
145
|
+
}))
|
146
|
+
|
147
|
+
));
|
148
|
+
|
149
|
+
return () => {
|
150
|
+
|
151
|
+
unSub();
|
152
|
+
|
153
|
+
};
|
154
|
+
|
155
|
+
}, []);
|
156
|
+
|
157
|
+
```
|
158
|
+
|
159
|
+
|
160
|
+
|
161
|
+
### Cloud Firestoreのコンソール画面
|
162
|
+
|
75
163
|
「training_posts」や「comments」という名前はないよ、とエラー文を解釈してコンソール画面を確認してみましたが、
|
76
164
|
|
77
165
|
タイプミスもないようですし、なぜアクセスできないのかが分からないです。
|