Skip to content
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 #2594

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open

Conversation

YuliiaShatkovska
Copy link

Copy link

@hma-3 hma-3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job!
Have just a few suggestions⬇️

Comment on lines +22 to +23
useEffect(() => {
setIsLoading(true);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you don't have to set loader to true here, just change the initial value in the state

const [isLoading, setIsLoading] = useState(true);

<form className="field has-addons">
<p className="control">
<span className="select">
<select data-cy="statusSelect" onChange={handleSelectFilter}>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add value to select

</td>
</tr>
return (
<tr data-cy="todo" className="" key={id}>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

row needs to have class 'has-background-info-light' when selected

Comment on lines 37 to 45
{completed ? (
<td className="is-vcentered">
<span className="icon" data-cy="iconCompleted">
<i className="fas fa-check" />
</span>
</td>
) : (
<td className="is-vcentered" />
)}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move condition inside td and then you won't have to write it twice

Comment on lines +21 to +22
useEffect(() => {
setIsLoading(true);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you don't have to set loader to true here, just change the initial value in the state
const [isLoading, setIsLoading] = useState(true);

same

Comment on lines +64 to +68
{completed ? (
<strong className="has-text-success">Done</strong>
) : (
<strong className="has-text-danger">Planned</strong>
)}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have mixed feelings about this😅
it may be worth moving the condition inside strong to avoid duplication, but I think this is a moot point here

Comment on lines 23 to 24
default:
return todo;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

filter callback should return boolean value. here it's still working, but it would be better to return just true

Copy link

@mateacademy-ai-mentor mateacademy-ai-mentor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job on the code! 👏 However, there are a few improvements that need to be made. Please address the issues in the getFilteredTodos function and consider the provided feedback for naming conventions and direct DOM manipulation. Keep up the good work! 💪

✨ Please rate this review in the Platform's notification center. I will be grateful for your feedback! ✨


export const App: React.FC = () => {
const [todos, setTodos] = useState<Todo[]>([]);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like you are initializing your state with props. This can be problematic because when the props change, your state won't be updated. You should consider using a different approach. Here are some resources that explain this in more detail: here, here and here

.finally(() => setIsLoading(false));
}, []);

const visibleTodos = getFilteredTodos(todos, { query, selectedFilter });

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are generating a new array on each render by calling getFilteredTodos(todos, { query, selectedFilter }). This can lead to performance issues as a new array is generated on every render. Consider using useMemo to avoid unnecessary array generation.

src/App.tsx Outdated
@@ -17,18 +36,32 @@
<h1 className="title">Todos:</h1>

<div className="block">
<TodoFilter />
<TodoFilter
setSelectedFilter={setSelectedFilter}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The setSelectedFilter and setQuery methods do not follow the naming conventions for event handler functions. According to the conventions, handler names should start with 'handle' and include the name of the event. For example, setSelectedFilter could be renamed to handleFilterChange. Here is a link to the article that explains this in detail: here

<span className="select">
<select data-cy="statusSelect" onChange={handleSelectFilter}>
{filters.map(filter => (
<option value={filter.toLowerCase()} key={filter}>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are generating keys for your list items on render. It's not the best approach because React uses keys to identify which items have changed, are added, or are removed and it may negatively impact performance. Keys should be stable, predictable, and unique for every set of elements. You can read more about it here.

Comment on lines 17 to 23
const handleSelectFilter = (event: React.ChangeEvent<HTMLSelectElement>) => {
setSelectedFilter(event.target.value as Filters);
};

const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setQuery(event.target.value.trimStart());
};

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your method names handleSelectFilter and handleInputChange are not following the naming conventions for methods in React. It's a good practice to name event handlers with the prefix 'on' and the part that describes what the event is. For example, handleSelectFilter can be renamed to onFilterChange and handleInputChange can be renamed to onInputChange. You can read more about it here.


export const TodoModal: React.FC = () => {
return (

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are interacting with the DOM directly by using class names. This is not recommended in React. Consider using a library like classnames to handle class names conditionally.


{' by '}

<a href="mailto:[email protected]">Leanne Graham</a>
<a href={`mailto:${user?.email}`}>{user?.name}</a>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are creating a mailto link here. Consider checking if the user's email exists before creating the link to avoid errors.

todos: Todo[],
{ query, selectedFilter }: Params,
) => {
let filteredTodos = [...todos];

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no need to create a copy of the todos array here, because the filter method does not mutate the original array but returns a new one.

Comment on lines 23 to 24
default:
return todo;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the default case of the switch statement, you're returning the entire todo object, which will always be truthy. This means that if the selected filter is not 'ACTIVE' or 'COMPLETED', all todos will be included in the filteredTodos array, regardless of their completed status. If this is the intended behavior, it would be clearer to return true in the default case to explicitly indicate that all todos should be included.

Comment on lines +28 to +36
const normilizedQuery = query.toLowerCase().trim();

if (normilizedQuery) {
filteredTodos = filteredTodos.filter(({ title }) => {
const normilizedTitle = title.toLowerCase();

return normilizedTitle.includes(normilizedQuery);
});
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The search query filtering is applied after the status filter. This means that if a user selects the 'ACTIVE' filter and then enters a search query, the search will only be applied to the active todos, not to all todos. If this is the intended behavior, it would be good to clarify it in the function's documentation. If not, you should apply the search query filter to the original todos array before applying the status filter.

Copy link

@mateacademy-ai-mentor mateacademy-ai-mentor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work so far! There are just a few minor issues that need to be addressed. Please correct the typo in the getFilteredTodos.ts file and consider the suggested improvements regarding naming conventions. Keep up the good work! 👍

✨ Please rate this review in the Platform's notification center. I will be grateful for your feedback! ✨

onChange={onFilterChange}
>
{filters.map(filter => (
<option value={filter.toLowerCase()} key={filter}>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid generating keys on render. This can lead to unexpected behavior in your application. Consider using a unique and consistent property from the data you're iterating over, if available.

handleFilterChange(event.target.value as Filters);
};

const inInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method name 'inInputChange' does not follow the recommended naming conventions. Consider renaming it to 'handleInputChange' or similar.

query,
selectedFilter,
}) => {
const onFilterChange = (event: React.ChangeEvent<HTMLSelectElement>) => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method name 'onFilterChange' does not follow the recommended naming conventions. Consider renaming it to 'handleFilterChange' or similar.

<tr
data-cy="todo"
className={isSelected ? 'has-background-info-light' : ''}
key={id}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not recommended to generate keys on render. The key should remain consistent across renders for performance reasons. Please consider using another approach.

data-cy="selectButton"
className="button"
type="button"
onClick={() => setSelectedTodo(todo)}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The naming convention for the method is not followed. Please consider following the recommended naming conventions for methods. For example, the method could be renamed to handleSelectTodo.

export const TodoModal: React.FC<Props> = ({
selectedTodo,
setSelectedTodo,
}) => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are initializing your state with props, which is generally not recommended. This can lead to bugs and unpredictable behavior. Here are some resources explaining why this is a bad practice: here, here and here.


const handleCloseModal = () => {
setSelectedTodo(null);
};

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your method name handleCloseModal does not follow the recommended naming conventions for event handlers in React. Consider renaming it to onCloseModal or handleModalClose. Here are some handy naming conventions for event handler functions/props in React.


export const TodoModal: React.FC = () => {
return (

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are interacting with the DOM directly by using className to define classes. It is recommended to use the classnames library for defining classes conditionally in React.

Copy link

@mateacademy-ai-mentor mateacademy-ai-mentor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job on your code! There are a few minor issues that need attention, such as avoiding direct DOM manipulation, following naming conventions for event handlers, and considering potential issues with initializing state with props or empty values. Nonetheless, these are not critical and won't affect the functionality of your code. I believe you can handle these improvements. Keep up the good work! 🚀

✨ Please rate this review in the Platform's notification center. I will be grateful for your feedback! ✨


export const App: React.FC = () => {
const [todos, setTodos] = useState<Todo[]>([]);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are initializing your state with empty arrays and null values. This is not a problem per se, but it can potentially lead to unnecessary re-renders and bugs. It would be a good idea to consider the potential issues that might arise from this. Here are some resources that might help you understand this better: here, here and here.

<tr
data-cy="todo"
className={isSelected ? 'has-background-info-light' : ''}
key={id}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're generating a key based on the id property of the todo item. While this is fine if the id is unique and does not change, it can lead to issues if the id is not unique or changes over time. This is because React uses the key to identify elements and can have issues with re-rendering if the key changes. Consider using a more reliable way of generating keys. Read more about it here.

data-cy="selectButton"
className="button"
type="button"
onClick={() => setSelectedTodo(todo)}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function setSelectedTodo is directly modifying the state. This is a direct interaction with the DOM, which is something we want to avoid in React. Try to handle this kind of logic in the component's methods and use React's built-in methods to update the state. Also, consider following the naming conventions for event handlers as described here.

return (
<tr
data-cy="todo"
className={isSelected ? 'has-background-info-light' : ''}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're defining classes conditionally here. This is a good practice, but it can be done in a more readable and maintainable way using the classnames library. This library allows you to define classes in a declarative way and takes care of the conditional logic for you.

setSelectedTodo,
}) => {
const [isLoading, setIsLoading] = useState(false);
const [user, setUser] = useState<User | null>(null);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're initializing state with props. It might lead to bugs because React state updates are asynchronous. It's recommended to avoid initializing state with props. Here are some resources that explain why it's a bad practice: here, here and here.

.finally(() => setIsLoading(false));
}, [userId]);

const handleModalClose = () => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the naming conventions for methods in React, handlers for events should be named starting with 'handle' and the name of the event. For example, in your case, a better name for the method would be 'handleCloseModal'. It's a good practice to follow these conventions to make the code more readable and easier to understand. You can read more about it here.


export const TodoModal: React.FC = () => {
return (

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're interacting with the DOM directly by using the 'className' attribute. In React, it's recommended to avoid direct DOM manipulation as much as possible. Instead, you can use the 'classnames' library to define classes conditionally. You can find more information about it here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants