-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Solution #1569
base: master
Are you sure you want to change the base?
Solution #1569
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 job! I left some comments below. Maybe that will be useful.
Also, I couldn't open App.tsx in review mode, so I've written some notes here:
-
You can drop
finally {}
in try\catch block. The thing is, that everything after catch{} block will execute automatically regardless the result. -
Your statements in
if(...)
(I guess, I saw that in handleUpdate func and all sorts of it) look a bit too complicated - I guess, that's the result of having too many states and variables. Try to reduce anything that seems useless. You can even reuse your own code here. That will definitely clean it up a bit and make statements easier.
Anyway, that's just small suggestions. The todo app works as indented and that's the point! Good job!
import { Todo } from '../../types/Todo'; | ||
|
||
type Props = { | ||
onDoubleClickTodo: (todo: Todo) => void; |
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 have many props here. Some could be created within associated components, so your component won't rely on all of them from the outside.
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 have many props here. Some could be created within associated components, so your component won't rely on all of them from the outside.
Good point
data-cy="TodoLoader" | ||
className={classNames('modal overlay', { | ||
'is-active': | ||
idDeletedTodo === 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.
For this statement, you could create some variable, which combines all possible scenarios. For example: isLoading =todo.id === 0 || isDeleting === todo.id || isUpdating === todo.id || loadingTodos.includes(todo.id) ....
Something like that. You can create this variable in your component, outside the render.
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.
For this statement, you could create some variable, which combines all possible scenarios. For example:
isLoading =todo.id === 0 || isDeleting === todo.id || isUpdating === todo.id || loadingTodos.includes(todo.id) ....
Something like that. You can create this variable in your component, outside the render.
I think it should be simplified, just one condition is enough for example store loading todo ids and as AnderZerfall said loadingTodoIds.includes(todo.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 work 👍
Let's improve your solution. Also, I don't see any loaders when I click Clear completed
button, check the working example
{errorState[ErrorType.Input] && `Title should not be empty`} | ||
{errorState[ErrorType.Add] && `Unable to add a todo`} | ||
{(errorState[ErrorType.Delete] || | ||
errorState[ErrorType.CompletedDelete]) && | ||
`Unable to delete a todo`} | ||
{errorState[ErrorType.Update] && `Unable to update a todo`} |
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 just store a message in an error state. As it's a bad idea to do like you, you have to add more and more conditions here for each case
src/components/Footer/Footer.tsx
Outdated
<a | ||
href="#/" | ||
className={classNames('filter__link', { | ||
selected: filterType === FilterType.All, | ||
})} | ||
data-cy="FilterLinkAll" | ||
onClick={() => { | ||
setFilterType(FilterType.All); | ||
}} | ||
> | ||
All | ||
</a> | ||
|
||
<a | ||
href="#/active" | ||
className={classNames('filter__link', { | ||
selected: filterType === FilterType.Active, | ||
})} | ||
data-cy="FilterLinkActive" | ||
onClick={() => { | ||
setFilterType(FilterType.Active); | ||
}} |
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 links look almost the same. You can transform FilterType
into an array with Object.values/keys/entries
and map
through them to generate links
src/components/Header/Header.tsx
Outdated
|
||
return ( | ||
<header className="todoapp__header"> | ||
{!todos.length || ( |
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.
{!todos.length || ( | |
{!!todos.length && ( |
import { Todo } from '../../types/Todo'; | ||
|
||
type Props = { | ||
onDoubleClickTodo: (todo: Todo) => void; |
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 have many props here. Some could be created within associated components, so your component won't rely on all of them from the outside.
Good point
data-cy="TodoLoader" | ||
className={classNames('modal overlay', { | ||
'is-active': | ||
idDeletedTodo === 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.
For this statement, you could create some variable, which combines all possible scenarios. For example:
isLoading =todo.id === 0 || isDeleting === todo.id || isUpdating === todo.id || loadingTodos.includes(todo.id) ....
Something like that. You can create this variable in your component, outside the render.
I think it should be simplified, just one condition is enough for example store loading todo ids and as AnderZerfall said loadingTodoIds.includes(todo.id)
inputEditRef.current.removeEventListener('keydown', handleKeyDown); | ||
} | ||
}; | ||
}, [todoChangedTitle, inputEditRef]); |
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.
Fix linter errors. And it's better to avoid DOM manipulations in react
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 looks good, let's improve your solution a bit more!
src/App.tsx
Outdated
setTimeout(() => { | ||
setErrorState(ErrorType.Default); | ||
}, 3000); |
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.
please don't forget to clear setTimeout
src/App.tsx
Outdated
event.preventDefault(); | ||
setIsAllCompleted(false); | ||
|
||
if (!title.trim().length) { |
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.
please move title.trim()
to const and reuse
src/api/todos.ts
Outdated
export const USER_ID = 2179; | ||
|
||
export const getTodos = () => { | ||
return client.get<Todo[]>(`/todos?userId=${USER_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.
let's move /todos
to const and reuse
src/types/ErrorType.ts
Outdated
Input = 'Title should not be empty', | ||
Add = 'Unable to add a todo', | ||
Delete = 'Unable to delete a todo', | ||
// CompletedDelete = 'Unable to delete a completed todo', |
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.
please remove redundant comment
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.
Looks good to me, I'm approving it!
DEMO LINK