Skip to content

React-add-todo-form#3567

Open
FRANCISCOPELEGRINI wants to merge 3 commits intomate-academy:masterfrom
FRANCISCOPELEGRINI:master
Open

React-add-todo-form#3567
FRANCISCOPELEGRINI wants to merge 3 commits intomate-academy:masterfrom
FRANCISCOPELEGRINI:master

Conversation

@FRANCISCOPELEGRINI
Copy link

No description provided.

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.

Review Summary

Good job setting up the form and state management for adding new todos! However, there are a few critical issues that need to be addressed before this can be approved.

Here are the main points to work on:

  1. Todo Data Structure: The task requires each todo item to contain a full user object. Currently, you're looking up user details on every render. Instead, when a new todo is created, you should find the corresponding user from usersFromServer and embed the entire user object into the new todo item you add to the state.

  2. New Todo ID Generation: The logic for creating a new todo ID in App.tsx is based on the initial todosFromServer list. This will cause duplicate IDs if you add more than one todo. Please update this to calculate the new ID based on the current list of todos in your state.

  3. Error Handling: The error messages for the title and user select fields should disappear as soon as the user starts typing or selects a different option. Currently, they only disappear on the next successful submission.

  4. Component Structure: The logic for rendering a single todo item should be moved from App.tsx into the TodoInfo component, which is currently empty. Also, the TodoList component is being used to render <option> elements, which is not its intended purpose.

Addressing these points will bring your solution in line with the project requirements.


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

Important

Fix the issues, commit the changes, and then re-request my review using the Re-request review button2 in the Reviewers tab.

Tip

If you have any comments about this review, please leave a message in the Add a comment section below and mention me with the @mateacademy-ai-mentor tag3.
I will read your message during my next review of your pull request. Please do not reply directly to my comments, as that feature is not supported yet.

Caution

Do not close the pull request until the review is complete. Closing it early can lead to unexpected behavior and disrupt the review process.

Footnotes

  1. Rate AI review example

  2. Re-request AI review example

  3. Add AI review comments example

@@ -1 +1,14 @@
export const TodoList = () => {};
interface RInterface {

Choose a reason for hiding this comment

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

Interface names should be descriptive. RInterface doesn't explain what this interface represents. A name like User would be more appropriate.

email: string;
}

export const TodoList = (r: RInterface) => {

Choose a reason for hiding this comment

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

This violates checklist item #1: 'Don't use one-letter variable naming.' The parameter r should be replaced with a more descriptive name like user.

Also, the component is named TodoList, but its function is to render a single <option> for a user. This is misleading; a name like UserOption would be more accurate. The task requires a TodoList component to display the list of todos.

src/App.tsx Outdated
Comment on lines +14 to +19
interface TodoVar {
id: number;
title: string;
completed: boolean;
userId: number;
}

Choose a reason for hiding this comment

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

The task description requires each TODO item to have a user object. This interface should be updated to include a user property. This will allow you to prepare the data correctly and avoid looking up user information on every render.

src/App.tsx Outdated

export const App = () => {
const [selectedUser, setSelectedUser] = useState(0);
const [users, setUsers] = useState<TodoVar[]>(todosFromServer);

Choose a reason for hiding this comment

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

The state variable users is storing the list of todos, which can be confusing. It would be clearer to rename it to todos to accurately reflect its content.

src/App.tsx Outdated
const [users, setUsers] = useState<TodoVar[]>(todosFromServer);
const [aparecerTxt, SetAparecerTxt] = useState<boolean[]>([false, false]);
const [todoVar, setTodoVar] = useState<TodoVar>({
id: todosFromServer[todosFromServer.length - 1].id + 1,

Choose a reason for hiding this comment

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

The ID for a new todo is calculated based on the initial todosFromServer list. This means if you add multiple todos, they will have the same ID. The new ID should be calculated from the current list of todos in your state (users). This logic is also repeated in the cleanTodo function, which is a violation of the DRY principle (Checklist item #2).

src/App.tsx Outdated
Comment on lines +65 to +86
const onChangeTodo = (
event: ChangeEvent<HTMLInputElement | HTMLSelectElement>,
type: string,
) => {
if (type === 'title' && 'target' in event) {
setTodoVar(prev => ({
...prev,
title: (event as ChangeEvent<HTMLInputElement>).target.value,
}));

return;
}

if (type === 'user') {
const value =
typeof event === 'string'
? event
: (event as ChangeEvent<HTMLSelectElement>).target.value;

setTodoVar(prev => ({ ...prev, userId: Number(value) }));
}
};

Choose a reason for hiding this comment

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

The requirements state that an error message should be hidden immediately after any change to the field that has the error. You should add logic here to update the error state (aparecerTxt) and clear the corresponding error when the user types in the input or selects a user.

src/App.tsx Outdated
Comment on lines +116 to +121
<input
type="text"
data-cy="titleInput"
value={todoVar.title}
onChange={e => onChangeTodo(e, 'title')}
/>

Choose a reason for hiding this comment

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

The task requires adding labels and placeholders where they are needed. This input is missing a <label> and a placeholder attribute, which are important for accessibility and user experience. The same applies to the <select> element below.

src/App.tsx Outdated
<option disabled={isOpen} value="0">
Choose a user
</option>
{usersFromServer.map(r => TodoList(r))}

Choose a reason for hiding this comment

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

In React, it's a best practice to render components using JSX syntax (e.g., <TodoList user={r} />) rather than calling them as functions. Calling components as functions can lead to unexpected behavior with hooks and performance issues. Also, consider renaming the TodoList component to something more descriptive like UserOption, as it renders a single <option>.

src/App.tsx Outdated
Leanne Graham
</a>
</article>
{users.map((a: TodoVar, b: number) => {

Choose a reason for hiding this comment

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

This violates checklist item #1: "Don't use one-letter variable naming." Using names like a and b makes the code difficult to understand. Please use more descriptive names, such as todo and index.

Comment on lines +1 to +29
// interface User {
// id: number;
// name: string;
// username: string;
// email: string;
// }

// interface RInterface {
// id: number;
// title: string;
// completed: boolean;
// userId: number;
// }

// interface Props {
// a: RInterface;
// b: number;
// user: User;
// }

// export const TodoInfo: React.FC<Props> = ({ a, b, user }) => {
// return (
// <article>
// <h2>{a.title}</h2>
// <h2>{b}</h2>
// <h2>{user.name}</h2>
// </article>
// );
// };

Choose a reason for hiding this comment

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

This component is not implemented. The rendering logic for individual todo items should be placed here instead of directly inside the App component. Creating a dedicated TodoInfo component will make your code more modular and easier to maintain.

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.

Review Summary

I am requesting changes because the application currently has several critical build and test failures that need to be resolved before it can be approved.

The most important issue is the application's structure. All state management (like the list of todos) and form logic should be in the App.tsx component, with data passed down to child components as props. Currently, this logic is incorrectly placed in TodoInfo.tsx, which violates a core requirement. [CHECKLIST ITEM #5]

Additionally, there are specific errors causing tests to fail:

  • Components are being called as functions (e.g., Generator()) instead of being rendered with JSX (<Generator />), which is an anti-pattern in React.
  • The TodoList component expects props named a and b, but the tests pass todo, causing a runtime error. Please use descriptive prop names. [CHECKLIST ITEM #1]

Finally, remember that when creating a new todo, you must embed the entire user object, not just the userId. Addressing these points will get your project on the right track.


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

Important

Fix the issues, commit the changes, and then re-request my review using the Re-request review button2 in the Reviewers tab.

Tip

If you have any comments about this review, please leave a message in the Add a comment section below and mention me with the @mateacademy-ai-mentor tag3.
I will read your message during my next review of your pull request. Please do not reply directly to my comments, as that feature is not supported yet.

Caution

Do not close the pull request until the review is complete. Closing it early can lead to unexpected behavior and disrupt the review process.

Footnotes

  1. Rate AI review example

  2. Re-request AI review example

  3. Add AI review comments example

src/App.tsx Outdated
</section>
</div>
);
return Generator();

Choose a reason for hiding this comment

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

This is not the correct way to render a React component. Components should be rendered using JSX syntax (e.g., <Generator />), not called directly as functions. Calling a component as a function bypasses React's lifecycle and hook management, which can lead to bugs and unpredictable behavior.

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.

Review Summary

I am approving this submission as an educational override to help you progress, but there are a few critical points to address for future tasks. You've done a great job implementing the form logic for adding new todos!

The most important issue is that all state management (useState) and application logic must be located in the App.tsx component, not in child components like TodoInfo.tsx [CHECKLIST ITEM #5]. Data and functions should then be passed down as props. Additionally, please make sure to render components using JSX syntax (e.g., <UserInfo {...user} />) instead of calling them as functions, which is a React anti-pattern. The tests are also failing because the component in TodoInfo.tsx is named Generator but should be TodoInfo.

Keep up the great work, and focus on these architectural patterns going forward!


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

Footnotes

  1. Rate AI review example

@@ -1 +1,14 @@
export const UserInfo = () => {};
interface RInterface {

Choose a reason for hiding this comment

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

The interface name RInterface is not very descriptive. A name like User or UserInfoProps would better describe the data it represents.

email: string;
}

export const UserInfo = (r: RInterface) => {

Choose a reason for hiding this comment

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

This component is being called as a function from its parent, which is a React anti-pattern. Components should always be rendered using JSX syntax (<UserInfo {...props} />).

To fix this, you should change the signature to accept a props object. For example: export const UserInfo = ({ id, name }: UserInfoProps) => { ... }.

Also, the parameter r violates checklist item #1, which advises against one-letter variable names. Using a more descriptive name like user would improve readability.


export const UserInfo = (r: RInterface) => {
return (
<option value={r.id} key={r.id}>

Choose a reason for hiding this comment

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

The key prop should be applied to the component instance inside the .map() loop in the parent component, not on the <option> element here. React uses the key on the list items themselves to track them.

For example, in the parent component: {users.map(user => <UserInfo key={user.id} {...user} />)}

Comment on lines +20 to +26
setUsers: React.Dispatch<React.SetStateAction<TodoVar[]>>;
}

export const TodoList: React.FC<TodoListProps> = ({
todo,
index,
setUsers,

Choose a reason for hiding this comment

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

Passing the setUsers state setter and the index prop directly to a child component creates tight coupling, making this component less reusable and dependent on the parent's implementation. A better approach is to pass a specific callback function (e.g., onComplete(id: number)) that the parent defines. This would also allow you to use the unique todo.id for updates, which is more reliable than an array index.

index,
setUsers,
}) => {
const setTrue = (e: React.MouseEvent<HTMLAnchorElement>) => {

Choose a reason for hiding this comment

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

This violates checklist item #1: 'Don't use one-letter variable naming.' Please use a more descriptive name for the event object, such as event.

export const Generator = () => {
const [users, setUsers] = useState<TodoVar[]>(
todosFromServer.map(todo => {
const fullUser = usersFromServer.find(u => u.id === todo.userId)!;

Choose a reason for hiding this comment

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

This violates checklist item #1: 'Don't use one-letter variable naming.' Please use a more descriptive name like user instead of u. This suggestion also applies to e for events and r in the .map() on line 141.

const [isOpen, setIsOpen] = useState<boolean>(false);

const [todoVar, setTodoVar] = useState<TodoVar>({
id: users[users.length - 1].id + 1,

Choose a reason for hiding this comment

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

The requirement is to use the "largest id in the array + 1". This implementation assumes the users array (which actually contains todos) is always sorted by ID. This is not a safe assumption. A more robust way to find the largest ID would be to iterate through all todos, for example: Math.max(0, ...users.map(todo => todo.id)) + 1.

id: users[users.length - 1].id + 1,
title: '',
completed: false,
user: usersFromServer[0],

Choose a reason for hiding this comment

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

The initial user for a new todo should not be a valid user from the list. This breaks the validation logic because todoVar.user.id will not be 0, allowing the form to be submitted without the user making a selection. The initial state should represent that no user has been chosen, for instance, by using a placeholder user object with id: 0.

Comment on lines +48 to +53
setTodoVar({
id: users[users.length - 1].id + 1,
title: '',
completed: false,
user: usersFromServer[0],
});

Choose a reason for hiding this comment

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

The object being created here is a repetition of the initial state defined for todoVar on lines 40-45. This violates the DRY (Don't Repeat Yourself) principle from checklist #2. You should extract this object creation logic into a reusable function to avoid duplication.

Choose a user
</option>

{usersFromServer.map(r => UserInfo(r))}

Choose a reason for hiding this comment

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

In React, components must be rendered using JSX syntax (<Component />), not called as plain functions (Component()). This was also mentioned in the previous review. Calling components as functions can lead to issues with hooks and performance.

This should be changed to:

{usersFromServer.map(user => (
  <UserInfo key={user.id} id={user.id} name={user.name} />
))}

You will also need to update the UserInfo component to receive props correctly instead of a single argument.

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.

2 participants