-
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
add task solution #1220
base: master
Are you sure you want to change the base?
add task solution #1220
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.
Thank you for your hard work on this project! 😊 While your code is well-structured and mostly meets the task requirements, there are a few critical issues that need to be addressed before we can approve the pull request:
-
Error Handling: There is a lack of comprehensive error handling for API requests and user actions like adding or deleting comments. Implementing a retry mechanism and user-friendly error notifications is crucial for a better user experience.
-
PropTypes: The absence of
propTypes
in your components means there's no type checking for props, which is essential for maintaining code quality and preventing bugs. -
Direct DOM Manipulation: The use of
document.addEventListener
anddocument.removeEventListener
in theUserSelector
component should be refactored to utilize React's event handling to align with best practices. -
Key Generation: Generating keys using the index in the
map
function can lead to issues. Ensure that a unique identifier from the data is used instead. -
State Initialization: Ensure that all expected keys in the
isLoading
andshowError
states are initialized to prevent undefined errors.
Please address these issues to enhance the functionality and maintainability of your code. Once resolved, feel free to resubmit for review. Keep up the great work, and I'm confident you'll nail it! 🚀
✨ Please rate this review in the Platform's notification center. I will be grateful for your feedback! ✨
🔄 Fix the issues, commit the changes, and then re-request my review using the Re-request review
button in the Reviewers tab.
src/App.tsx
Outdated
const [usersFromServer, setUsersFromServer] = useState<User[]>([]); | ||
const [commentsForPost, setCommentsForPost] = useState<Comment[]>([]); | ||
const [postsForUser, setPostsForUser] = useState<Post[]>([]); | ||
const [isLoading, setIsLoading] = useState<IsLoading>({}); |
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 initial state for isLoading
is set as an empty object. Ensure that all expected keys (e.g., postListLoading
, PostDetailsLoading
) are initialized to false
to avoid potential undefined errors when accessing these properties.
src/App.tsx
Outdated
const [commentsForPost, setCommentsForPost] = useState<Comment[]>([]); | ||
const [postsForUser, setPostsForUser] = useState<Post[]>([]); | ||
const [isLoading, setIsLoading] = useState<IsLoading>({}); | ||
const [showError, setShowError] = useState<ShowError>({}); |
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.
Similar to isLoading
, the initial state for showError
is set as an empty object. Consider initializing all expected error keys (e.g., usersError
, PostsLoadingError
, PostDetailsError
) to false
to prevent undefined errors.
src/App.tsx
Outdated
setPostSelected(null); | ||
setPostsForUser(posts); | ||
}) | ||
.catch(() => handleSetError('PostsLoadingError', true)) |
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 error key 'PostsLoadingError' in handleSetError
should match the key used in the renderError
function. Ensure consistency in naming to avoid errors in error rendering.
src/App.tsx
Outdated
setIsLoading((prev) => ({ ...prev, PostDetailsLoading: true })); | ||
getCommentsForPost(postSelected.id) | ||
.then(setCommentsForPost) | ||
.catch(() => handleSetError('PostDetailsError', true)) |
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 error key 'PostDetailsError' in handleSetError
should match the key used in the renderError
function. Ensure consistency in naming to avoid errors in error rendering.
{postSelected && ( | ||
<PostDetails | ||
postSelected={postSelected} | ||
PostDetailsLoading={isLoading.PostDetailsLoading} |
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.
Ensure that isLoading.PostDetailsLoading
is correctly initialized and updated. If the key is not initialized in the state, it might lead to undefined errors.
src/types/AppErrors.ts
Outdated
@@ -0,0 +1,5 @@ | |||
export interface ShowError { | |||
postListError?: boolean; | |||
PostDetailsError?: 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.
Ensure that the naming of PostDetailsError
is consistent with how errors are referenced in the application. Consistency in naming helps avoid confusion and potential errors.
src/types/AppErrors.ts
Outdated
export interface ShowError { | ||
postListError?: boolean; | ||
PostDetailsError?: boolean; | ||
usersError?: 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.
Ensure that the naming of usersError
is consistent with how errors are referenced in the application. Consistency in naming helps avoid confusion and potential errors.
src/types/Loading.ts
Outdated
@@ -0,0 +1,5 @@ | |||
export interface IsLoading { | |||
postListLoading?: 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.
Ensure that the naming of postListLoading
is consistent with how loading states are referenced in the application. Consistency in naming helps avoid confusion and potential errors.
src/types/Loading.ts
Outdated
@@ -0,0 +1,5 @@ | |||
export interface IsLoading { | |||
postListLoading?: boolean; | |||
PostDetailsLoading?: 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.
Ensure that the naming of PostDetailsLoading
is consistent with how loading states are referenced in the application. Consistency in naming helps avoid confusion and potential errors.
src/types/Loading.ts
Outdated
export interface IsLoading { | ||
postListLoading?: boolean; | ||
PostDetailsLoading?: boolean; | ||
usersLoading?: 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.
Ensure that the naming of usersLoading
is consistent with how loading states are referenced in the application. Consistency in naming helps avoid confusion and potential errors.
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.
Your code demonstrates a solid understanding of React and its components, with many aspects implemented correctly, such as state management, key generation, and conditional rendering. However, there are several areas for improvement that you should address to enhance the functionality and maintainability of your application:
-
Error Handling: While basic error handling is in place, consider providing more detailed error messages or implementing retry mechanisms for API requests, especially for comment loading and deletion. This will improve the user experience significantly.
-
PropTypes: Ensure that
propTypes
are defined for all components to maintain type safety and prevent potential bugs. -
Direct DOM Manipulation: Refactor the
handleClickOutside
logic in theUserSelector
component to use React's event handling system instead ofwindow.addEventListener
. This aligns with React best practices. -
Accessibility: Improve accessibility by adding ARIA attributes where necessary, such as
aria-selected
for active users. -
Code Clarity: Consider adding comments to explain the purpose of certain variables, like the
condition
variable, to aid future maintainers. -
Validation: Enhance form validation by adding checks for email format and ensuring the loading state is reset if validation fails.
These improvements will not only enhance the user experience but also ensure your code is robust and maintainable. Keep up the great work and continue to refine your skills! 😊
✨ Please rate this review in the Platform's notification center. I will be grateful for your feedback! ✨
const [userSelected, setUserSelected] = useState<User | null>(null); | ||
const [postSelected, setPostSelected] = useState<Post | null>(null); | ||
const [usersFromServer, setUsersFromServer] = useState<User[]>([]); | ||
const [commentsForPost, setCommentsForPost] = useState<Comment[]>([]); | ||
const [postsForUser, setPostsForUser] = useState<Post[]>([]); | ||
const [isLoading, setIsLoading] = useState<IsLoading>({ | ||
postListLoading: false, | ||
PostDetailsLoading: false, | ||
usersLoading: false, | ||
}); | ||
|
||
<div className="block" data-cy="MainContent"> | ||
<p data-cy="NoSelectedUser">No user selected</p> | ||
const [showError, setShowError] = useState<ShowError>({ | ||
usersError: false, | ||
PostsLoadingError: false, | ||
PostDetailsError: false, | ||
}); |
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 state initialization for isLoading
and showError
is correctly done, ensuring that all expected keys are initialized. This prevents potential undefined errors.
getUsers() | ||
.then(setUsersFromServer) | ||
.catch(() => setShowError(prev => ({ ...prev, usersError: true }))); |
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.
Consider implementing a retry mechanism or providing more detailed error messages to improve user experience when fetching users fails.
getPostsForUser(userSelected.id) | ||
.then(posts => { | ||
setPostSelected(null); | ||
setPostsForUser(posts); | ||
}) | ||
.catch(() => | ||
setShowError(prev => ({ ...prev, PostsLoadingError: true })), | ||
) | ||
.finally(() => | ||
setIsLoading(prev => ({ ...prev, postListLoading: false })), | ||
); |
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.
Similar to the previous comment, consider enhancing error handling for fetching posts by implementing retries or more informative error messages.
getCommentsForPost(postSelected.id) | ||
.then(setCommentsForPost) | ||
.catch(() => | ||
setShowError(prev => ({ ...prev, PostDetailsError: true })), | ||
) | ||
.finally(() => | ||
setIsLoading(prev => ({ ...prev, PostDetailsLoading: false })), | ||
); |
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.
Again, consider improving error handling for fetching comments with retries or more user-friendly error notifications.
const renderError = (errorKey: keyof ShowError) => | ||
showError[errorKey] && ( | ||
<div className="notification is-danger" data-cy={`${errorKey}`}> | ||
Something went wrong! | ||
</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.
The renderError
function is a good approach to handle error display. Ensure that the error messages are informative for the user.
<button | ||
type="button" | ||
data-cy="PostButton" | ||
className={classNames("button is-link", {"is-light": condition})} |
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 use of classNames
to conditionally apply the 'is-light' class is correct and helps in managing the button's appearance based on the condition
.
{postsForUser.length === 0 ? ( | ||
<div className="notification is-warning" data-cy="NoPostsYet"> | ||
No posts yet | ||
</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.
The conditional rendering for displaying a notification when there are no posts is correctly implemented and provides a clear user message.
{postsForUser.map((post) => ( | ||
<PostListElement | ||
post={post} | ||
key={post.id} | ||
setPostSelected={setPostSelected} | ||
isLight={isLight} | ||
setIsLight={setIsLight} | ||
/> | ||
))} |
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 use of post.id
as a key in the map
function is appropriate, ensuring each post element has a unique identifier.
useEffect(() => { | ||
window.addEventListener('click', handleClickOutside); | ||
|
||
return () => { | ||
window.removeEventListener('click', handleClickOutside); | ||
}; | ||
}, []); |
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.
Consider refactoring the handleClickOutside
logic to use React's event handling system instead of directly manipulating the DOM with window.addEventListener
. This aligns with React best practices and ensures better integration with the component lifecycle.
<div className="dropdown-trigger"> | ||
<button | ||
type="button" | ||
className="button" | ||
aria-haspopup="true" | ||
aria-controls="dropdown-menu" | ||
onClick={() => setShowUsers(prev => !prev)} |
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 toggle logic for showing users is correctly implemented, providing a clear user interaction for opening and closing the dropdown.
No description provided.