总结 在Workshop2当中,我们完成了这样的一个页面
在这个workshop3当中,我们将给这个页面添加路由和新的评论页面
路由 我们主要用<Router />
或<Link />
<Router />
例子
子路由的路径是相对于其父路由的 ,而不是整个应用的根路径。具体来说,<DashboardHome path="/" />
是定义在 <Dashboard>
内部的,它的路径会被解释为相对于 Dashboard
的 path="dashboard"
,而不会直接作用于全局的 /
。
<Link />
网络请求 我们的最终目的:
当前结构:
Feed.js
的Story
Step 0: 替换 Profile
组件为 Feed
组件
将原本的 Profile
组件替换成 Feed
组件,作为展示故事的主要容器。
Step 1: 声明状态,使用 GET 请求加载所有评论数据
在组件中声明状态,用来存储从数据库加载的评论数据。
使用 GET 请求从数据库获取所有评论并更新状态。
Step 2: 使用 Dummy 数据渲染 SingleStory
组件
使用虚拟的(Dummy)数据来测试并渲染 SingleStory
组件,模拟如何展示每一条故事。
Step 3: 使用 .map()
方法将故事数据(来自 GET 请求)映射为单个故事
通过 .map()
方法遍历获取到的故事数据,将每个故事渲染成 SingleStory
组件。
Step 4: 将 NewPostInput
包裹在一个新的组件中,并添加发布功能
将 NewPostInput
组件封装到一个新的组件中,并实现发布新故事的功能,允许用户提交数据。
Step 6- 8: 在每个story下面显示评论,同时添加评论框
Step 1-4结果 story
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 const Feed = ( ) => { const [stories, setStories] = useState ([]); useEffect (() => { get ("/api/stories" ).then ((storyObjs ) => { setStories (storyObjs); }); }, []); let storiesList = null ; const hasStories = stories.length !== 0 ; if (hasStories) { storiesList = stories.map ((storyObj ) => ( <SingleStory creator_name ={storyObj.creator_name} content ={storyObj.content} /> )); } else { storiesList = <div > No stories!</div > ; } return ( <div > <NewStory /> {storiesList} </div > ); };
newPostInput.js
1 2 3 4 5 6 7 8 const NewStory = ( ) => { const addStory = (value ) => { const body = { content : value }; post ("/api/story" , body); }; return <NewPostInput defaultText ="New Story" onSubmit ={addStory} /> ; };
目前结果:
Step 6-9 最终目的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 const Feed = ( ) => { const [stories, setStories] = useState ([]); useEffect (() => { get ("/api/stories" ).then ((storyObjs ) => { setStories (storyObjs); }); }, []); let storiesList = null ; const hasStories = stories.length !== 0 ; if (hasStories) { storiesList = stories.map ((storyObj ) => ( <Card _id ={storyObj._id} creator_name ={storyObj.creator_name} content ={storyObj.content} /> )); } else { storiesList = <div > No stories!</div > ; } return ( <div > <NewStory /> {storiesList} </div > ); }; export default Feed ;
card.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 const Card = (props ) => { const [comments, setComments] = useState ([]); useEffect (() => { get ("/api/comment" , { parent : props._id }).then ((commentItems ) => { setComments (commentItems); }); }, []); let commentsList = null ; const hasComments = comments.length !== 0 ; if (hasComments) { commentsList = comments.map ((commentObj ) => ( <SingleComment _id ={commentObj._id} creator_name ={commentObj.creator_name} content ={commentObj.content} /> )); } else { commentsList = <div > No comments!</div > ; } return ( <div className ="Card-container" > <SingleStory _id ={props._id} creator_name ={props.creator_name} content ={props.content} /> {commentsList} <NewComment storyId ={props._id} /> </div > ) }; export default Card ;
newComment
1 2 3 4 5 6 7 8 const NewComment = (props ) => { const addComment = (value ) => { const body = { parent : props.storyId , content : value }; post ("/api/comment" , body); }; return <NewPostInput defaultText ="New Comment" onSubmit ={addComment} /> ; };
Step10
1 2 3 4 5 6 7 8 9 const Card = (props ) => { .... return ( <div className ="Card-container" > <SingleStory _id ={props._id} creator_name ={props.creator_name} content ={props.content} /> <CommentsBlock storyId ={props._id} comments ={comments} addNewComment ={addNewComment} /> </div > ); };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 const CommentsBlock = (props ) => { return ( <div className ="Card-commentSection" > <div className ="story-comments" > {props.comments.map((comment) => ( <SingleComment key ={ `SingleComment_ ${comment._id }`} _id ={comment._id} creator_name ={comment.creator_name} content ={comment.content} /> ))} <NewComment storyId ={props.storyId} addNewComment ={props.addNewComment} /> </div > </div > ); };
最后一步-实时评论 我们会发现,我们每次提交故事或评论的时候,都需要重新刷新才会显示出外面新添加的评论,我们要怎么修改我们的代码才能做到 我们一提交,页面就显示出新内容?
我们的stories
列表是存在Feed.js
当中,comment
列表是存在Card.js
当中,如果我们每次提交的时候都会调用他们的回调函数 的话就能实时更新了
Feed.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 const Feed = ( ) => { const [stories, setStories] = useState ([]); ... let storiesList = null ; const hasStories = stories.length !== 0 ; if (hasStories) { storiesList = stories.map ((storyObj ) => ( <Card _id ={storyObj._id} creator_name ={storyObj.creator_name} content ={storyObj.content} /> )); } else { storiesList = <div > No stories!</div > ; } return ( <div > <NewStory /> {storiesList} </div > ); };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 const Feed = ( ) => { const [stories, setStories] = useState ([]); ... const addNewStory = (storyObj ) => { setStories (stories.concat ([storyObj])); }; let storiesList = null ; const hasStories = stories.length !== 0 ; if (hasStories) { storiesList = stories.map ((storyObj ) => ( <Card key ={ `Card_ ${storyObj._id }`} _id ={storyObj._id} creator_name ={storyObj.creator_name} content ={storyObj.content} /> )); } else { storiesList = <div > No stories!</div > ; } return ( <div > <NewStory addNewStory ={addNewStory} /> {storiesList} </div > ); };
card.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 const Card = (props ) => { const [comments, setComments] = useState ([]); ... let commentsList = null ; const hasComments = comments.length !== 0 ; if (hasComments) { commentsList = comments.map ((commentObj ) => ( <SingleComment _id ={commentObj._id} creator_name ={commentObj.creator_name} content ={commentObj.content} /> )); } else { commentsList = <div > No comments!</div > ; } return ( <div className ="Card-container" > <SingleStory _id ={props._id} creator_name ={props.creator_name} content ={props.content} /> <CommentsBlock storyId ={props._id} comments ={comments} /> </div > ) };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 const Card = (props ) => { const [comments, setComments] = useState ([]); ... const addNewComment = (commentObj ) => { setComments (comments.concat ([commentObj])); }; return ( <div className ="Card-container" > <SingleStory _id ={props._id} creator_name ={props.creator_name} content ={props.content} /> <CommentsBlock storyId ={props._id} comments ={comments} addNewComment ={addNewComment} /> </div > ); };
NewPostInput.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 const NewStory = ( ) => { const addStory = (value ) => { const body = { content : value }; post ("/api/story" , body); }; return <NewPostInput defaultText ="New Story" onSubmit ={addStory} /> ; }; const NewComment = (props ) => { const addComment = (value ) => { const body = { parent : props.storyId , content : value }; post ("/api/comment" , body); }; return <NewPostInput defaultText ="New Comment" onSubmit ={addComment} /> ; };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 const NewStory = (props ) => { const addStory = (value ) => { const body = { content : value }; post ("/api/story" , body).then ((story ) => { props.addNewStory (story); }); }; return <NewPostInput defaultText ="New Story" onSubmit ={addStory} /> ; }; const NewComment = (props ) => { const addComment = (value ) => { const body = { parent : props.storyId , content : value }; post ("/api/comment" , body).then ((comment ) => { props.addNewComment (comment); }); }; return <NewPostInput defaultText ="New Comment" onSubmit ={addComment} /> ; };