Atifjahangir238 / Todo-app

0 stars 0 forks source link

Code Review Suggesstions #1

Open mohammad-ammad opened 3 weeks ago

mohammad-ammad commented 3 weeks ago

IMPROVEMENT # 1

image

Using setListTodo((prev) => [...prev, text]) is generally considered a better practice than setListTodo([...listTodo, text]). Here's why:

  1. State Consistency: React's state updates are asynchronous, so when you use the current state (listTodo), it might not have the most up-to-date value. Using the callback function (prev) => ... guarantees that you are working with the latest state, avoiding potential bugs due to stale state.

  2. Performance: The callback method ensures that React doesn't have to perform unnecessary re-renders if the state is updated quickly in succession.

Example:

setListTodo((prev) => [...prev, text]); // Recommended

This ensures you're always appending text to the most recent version of listTodo.

IMPROVEMENT # 2:

image

Instead of using splice(), which modifies the array directly and might lead to unexpected behavior, it's generally better to use filter() to create a new array without mutating the original one.

Here’s an optimized version using filter():

const deleteListItem = (key) => {
  setListTodo((prevListTodo) => prevListTodo.filter((_, index) => index !== key));
};

Why this is better:

  1. Immutability: filter() returns a new array, ensuring the original state remains untouched, which is a good practice in functional programming and React.
  2. Readability: The intent is clearer: you're creating a new array that excludes the item at the specified index.
  3. Performance: There's no need to create an extra copy of the array before modifying it. You're directly creating a new array with filter() based on the previous state.

This method is cleaner and adheres to React's principles of immutability.

IMPROVEMENT # 3:

image

Using prop destructuring directly in the function signature can often improve readability and make your code more concise. Instead of accessing props.someProp multiple times, you can extract the specific properties you're interested in right away.

Here’s a comparison:

Without destructuring (less concise):

export default function AddTodo(props) {
  return (
    <div>
      <p>{props.text}</p>
      <button onClick={props.onClick}>Add Todo</button>
    </div>
  );
}

With destructuring (more concise):

export default function AddTodo({ text, onClick }) {
  return (
    <div>
      <p>{text}</p>
      <button onClick={onClick}>Add Todo</button>
    </div>
  );
}

Why destructuring is better:

  1. Conciseness: Destructuring reduces the need to repeatedly type props.someProp.
  2. Readability: It's clear right at the beginning of the function which props are being used. This is especially useful when there are many props being passed.
  3. Easier maintenance: If you need to add, remove, or rename props, it's simpler and easier to manage directly in the function signature.
  4. Best practice: In modern JavaScript and React, destructuring is often considered a cleaner and more idiomatic approach.

Overall, destructuring is recommended when you're handling multiple props.

IMPROVMENT # 4:

Your TodoList component is generally clean and well-structured. Below are some code review suggestions to further improve it:

1. Destructure Props:

As discussed earlier, destructuring props improves readability. You can destructure props directly in the function signature.

2. Use Callback with setState:

Instead of using setIsStrikethrough(!isStrikethrough), it's generally safer to use a callback to ensure you're always working with the latest state.

3. Use Semantic HTML for Accessibility:

The div with the text-center class could be replaced with a label or span to improve semantics and accessibility.

4. Consider onChange for Checkbox:

While onClick works for the checkbox, onChange is the more appropriate event handler for form elements like checkboxes.

5. Use Unique id for Checkbox:

Each checkbox should have a unique id to avoid potential conflicts, especially if you render multiple TodoList components.

6. Event Handler on Icon:

Instead of attaching onClick to the whole div surrounding the delete icon, attach it directly to the i tag to make the click target more specific.

7. Class Names:

Make sure your class names like "border-rouded" are correct (probably meant to be "border-rounded"). Spelling mistakes can lead to CSS not being applied properly.

Here's the refactored version of your code:

Refactored Code:

import React, { useState } from 'react';

export default function TodoList({ item, deleteListItem, index }) {
  const [isStrikethrough, setIsStrikethrough] = useState(false);

  const toggleStrikethrough = () => {
    setIsStrikethrough((prev) => !prev); // Use callback for safety
  };

  return (
    <div className="row container mt-3 m-auto text-start border border-dark-2 p-2 rounded">
      <div className="col-4">
        <div className="form-check">
          <input
            className="form-check-input"
            onChange={toggleStrikethrough} // Use onChange for checkboxes
            type="checkbox"
            id={`flexCheckDefault-${index}`} // Unique ID for each checkbox
          />
        </div>
      </div>
      <div
        className="col-4 text-center"
        style={{
          textDecoration: isStrikethrough ? 'line-through' : 'none', // Strikethrough based on state
          fontSize: '18px',
        }}
      >
        {item}
      </div>
      <div className="col-4 text-end">
        <i
          className="bi bi-trash3 link-danger"
          onClick={() => deleteListItem(index)} // Attach directly to the icon
          role="button" // For accessibility
          aria-label="Delete item"
        />
      </div>
    </div>
  );
}

Key Improvements:

  1. Prop Destructuring: Simplifies access to item, deleteListItem, and index.
  2. State Safety: Used callback in setIsStrikethrough((prev) => !prev) to ensure state is always updated correctly.
  3. Checkbox onChange: Handled checkbox changes with onChange, which is more appropriate for form elements.
  4. Unique ID: Added a unique id to the checkbox to ensure it doesn’t clash with other checkboxes if multiple TodoList components are rendered.
  5. Improved Event Handling: Click event is directly tied to the icon instead of the surrounding div, ensuring better UX.
Atifjahangir238 commented 3 weeks ago

Thank you so much for your valuable suggestion! I truly appreciate the time you took to share your insights. I'll definitely apply your advice to enhance my learning process.