-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
implement functionality for dynamic list of posts #921
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good work 👍
Let's improve your solution slightly
src/App.tsx
Outdated
{user && posts.length === 0 ? ( | ||
<div | ||
className="notification is-warning" | ||
data-cy="NoPostsYet" | ||
> | ||
No posts yet | ||
</div> | ||
) : null} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{user && posts.length === 0 ? ( | |
<div | |
className="notification is-warning" | |
data-cy="NoPostsYet" | |
> | |
No posts yet | |
</div> | |
) : null} | |
{user && posts.length === 0 && ( | |
<div | |
className="notification is-warning" | |
data-cy="NoPostsYet" | |
> | |
No posts yet | |
</div> | |
)} |
You can use just and
operator in this case
src/App.tsx
Outdated
{posts.length > 0 && user ? ( | ||
<PostsList /> | ||
) : null} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same
src/api/comments.ts
Outdated
// export const createComment = (data: Comment) => { | ||
// return client.post<Comment>('/comments', data); | ||
// }; | ||
|
||
export const createComment = ({ | ||
name, email, body, postId, | ||
}: Omit<Comment, 'id'>) => { | ||
return client.post<Comment>('/comments', { | ||
name, email, body, postId, | ||
}); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// export const createComment = (data: Comment) => { | |
// return client.post<Comment>('/comments', data); | |
// }; | |
export const createComment = ({ | |
name, email, body, postId, | |
}: Omit<Comment, 'id'>) => { | |
return client.post<Comment>('/comments', { | |
name, email, body, postId, | |
}); | |
}; | |
export const createComment = (comment: Omit<Comment, 'id'>) => { | |
return client.post<Comment>('/comments', comment); | |
}; |
Don't leave comments, and you don't need destructing in this case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I use this shortcut, the comment will not be created on the server and I get an error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO - You are not sure what data would actually be passed to this function - so explicitly sending only the required data is OK
src/components/NewCommentForm.tsx
Outdated
const handleChangeForm = ( | ||
event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>, | ||
) => { | ||
event.preventDefault(); | ||
|
||
setFormData(prev => ({ ...prev, [event.target.name]: event.target.value })); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const handleChangeForm = ( | |
event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>, | |
) => { | |
event.preventDefault(); | |
setFormData(prev => ({ ...prev, [event.target.name]: event.target.value })); | |
}; | |
const handleChangeForm = ( | |
event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>, | |
) => { | |
const { name, value } = event.target; | |
setFormData(prev => ({ ...prev, [name]: value })); | |
}; |
Why do you do event.preventDefault();
?
src/components/NewCommentForm.tsx
Outdated
Add | ||
</button> | ||
</div> | ||
{/* is-loading */} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't leave comments
src/components/PostDetails.tsx
Outdated
|
||
export const PostDetails: React.FC = () => { | ||
const { post } = useContext(PostsContext); | ||
const { comments, setComments } = useContext(CommentsContext); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can create a hook for your contexts and in this case, you don't need to pass context every time:
const useComments = () => useContext(CommentsContext);
src/components/PostDetails.tsx
Outdated
.then(() => { | ||
setComments(prevComments => { | ||
return prevComments.filter(({ id }) => id !== commentId); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add catch
block
src/components/PostDetails.tsx
Outdated
<article className="message is-small" data-cy="Comment" key={id}> | ||
<div className="message-header"> | ||
<a href={`mailto:${email}`} data-cy="CommentAuthor"> | ||
{name} | ||
</a> | ||
<button | ||
data-cy="CommentDelete" | ||
type="button" | ||
className="delete is-small" | ||
aria-label="delete" | ||
onClick={() => handleDeleteComment(id)} | ||
> | ||
delete button | ||
</button> | ||
</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Create a Comment
component
src/components/PostsList.tsx
Outdated
</td> | ||
</tr> | ||
return ( | ||
<tr data-cy="Post" key={id}> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Create Post
component
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good job!
src/components/CurrentPost.tsx
Outdated
data-cy="PostButton" | ||
className={classnames('button is-link', { | ||
'is-light': post?.id !== id, | ||
})} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that is better
data-cy="PostButton" | |
className={classnames('button is-link', { | |
'is-light': post?.id !== id, | |
})} | |
data-cy="PostButton" | |
className={classnames('button', 'is-link', { | |
'is-light': post?.id !== id, | |
})} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point.
src/components/NewCommentForm.tsx
Outdated
<button type="submit" className="button is-link "> | ||
Add | ||
</button> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<button type="submit" className="button is-link "> | |
Add | |
</button> | |
<button type="submit" className="button is-link"> | |
Add | |
</button> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point.
<UsersProvider> | ||
<PostsProvider> | ||
<CommentsProvider> | ||
<ErrorProvider> | ||
<App /> | ||
</ErrorProvider> | ||
</CommentsProvider> | ||
</PostsProvider> | ||
</UsersProvider>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can create a component that will wrap the App with all providers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense - you should do it next time
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good job, but let's polish your code.
src/components/CurrentPost.tsx
Outdated
data-cy="PostButton" | ||
className={classnames('button is-link', { | ||
'is-light': post?.id !== id, | ||
})} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point.
src/components/NewCommentForm.tsx
Outdated
<button type="submit" className="button is-link "> | ||
Add | ||
</button> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point.
Co-authored-by: Roman Mirzoian <[email protected]>
Co-authored-by: Roman Mirzoian <[email protected]>
Co-authored-by: Roman Mirzoian <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall - good job! 👍
You are good at writing components - but there are some issues with overall architecture and components responsibility
Let's move on with this solution, but here are the items to keep in mind for the future:
- Mind the naming - all component and function names should be as descriptive as possible. For instance
CurrentPost
suggests that the component renders some specific post that the user is working on. But in your app, it is just an element of the list, soPost
or evenPostItem
fits better. Also - mind the grammar ;) - Try organizing components in the folders: for instance, you can create a subfolder 'components/PostList' and move all post-related components there (PostList, CurrentPost, CurrentComment, etc.)
- Don't overuse contexts - while this is a powerful tool, it has "dark sides". One of them is making the code more "coupled". Try making components as "dumb" and isolated as possible - it improves testability, makes supporting the code easier, etc. For instance - I would remove the
PostsContext
call from thePostList
and simply pass posts as an external property.
user: null, | ||
setUser: () => {}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
calling this currentUser
or selectedUser
would be a bit more readable
post: null, | ||
setPost: () => {}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as with user context - better call it selectedPost
, etc
|
||
interface ErrorContextType { | ||
isErrorHappen: boolean; | ||
setIsErrorHappen: React.Dispatch<React.SetStateAction<boolean>>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Grammar issue :)
Better hasErrorHappened
or just hasError
, etc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From how I see your scenario - it makes sense to merge CommentsContext
and PostsContext
The thing is, that you have currentPost
in the PostsContext
but comments do not make any sense without the Post
.
The main idea is minimizing the number of contexts, as managing large number of contexts is not the best experience
{isPostsExist && ( | ||
<div | ||
className="notification is-warning" | ||
data-cy="NoPostsYet" | ||
> | ||
No posts yet | ||
</div> | ||
)} | ||
|
||
<div | ||
className="notification is-danger" | ||
data-cy="PostsLoadingError" | ||
> | ||
Something went wrong! | ||
</div> | ||
{isPostListShown && ( | ||
<PostsList /> | ||
)} | ||
</> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are reading the posts in the App only to show this section
Possibly it makes sense to move the block "No posts yet" to the PostsList
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naming issue: just Comment
looks better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naming issue: just Post
or PostItem
looks better
DEMO LINK