skip to Main Content

I try to make simple project with React .I have a TodoItem component. My expectation is to change the border color after the checkbox is checked. However, after checking the checkbox, my component doesn’t change color. Am I doing something wrong? What steps should I take?

App.jxs

import './App.css'
import './components/TodoItem/TodoItem.jsx'
import TodoItem from './components/TodoItem/TodoItem.jsx'

function App() {
  return (
    <>
      <TodoItem taskName={'Clean House'} statusInit={true} ></TodoItem>
      <TodoItem taskName={'Read Book'} statusInit={false} ></TodoItem>
      <TodoItem taskName={'Clean Bed'} statusInit ={true} ></TodoItem>
    </>
  )
}

export default App

TodoItem.jsx

import "./TodoItem.css";
import { useState } from "react";

function TodoItem({ taskName, statusInit }) {

  const [status, setStatus] = useState(statusInit);
  const [count, setCount] = useState(0);
  let myClass = statusInit ? 'done' : 'todo-item'
 

  function checkBoxOnChange(e) {
    setStatus(e.target.checked);
    setCount(count + 1);
    statusInit = e.target.checked;
    myClass = statusInit ? 'done' : 'todo-item'
  }
  return (
    <>
      <main className={myClass}>
        <input 
          checked={status}
          type="checkbox"
          onChange={checkBoxOnChange}
          id="todo-item-status"
        />
        <p>{`${status}`}</p>
        <p>{taskName}</p>
        <p>{count}</p>
      </main>
    </>
  );
}

export default TodoItem;

TodoItem.css

.todo-item{
    width: 300px;
    margin: 16px;
    padding: 16px; 
    border: solid royalblue 2px;
    border-radius: 4px;
    display: flex;
    justify-content: space-between;
}

.done{
    width: 300px;
    margin: 16px;
    padding: 16px; 
    border: solid green 2px;
    border-radius: 4px;
    display: flex;
    justify-content: space-between;
}

3

Answers


  1. You don’t need to create a variable. Apply conditional className based on state, it will automatically re-render with different styles.

    <main className={status ? "done" : "todo-item"}></main>
    
    Login or Signup to reply.
  2. The statusInit value will remain true as it is a prop from the parent Component. Try log the value of statusInit value in the jsx part so that you can find the reason for not changing class properly.

    //In the TodoItem.js
    return (
        <>
          {console.log(statusInit)}
        </>
      );
    

    As you are maintaining a separate state called status, you can use that instead statusInit.

    //TodoItem.js
    import "./TodoItem.css";
    import { useState } from "react";
    
    function TodoItem({ taskName, statusInit }) {
    
      const [status, setStatus] = useState(statusInit);
      const [count, setCount] = useState(0);
      let myClass = status ? 'done' : 'todo-item'
     
    
      function checkBoxOnChange(e) {
        setStatus(e.target.checked);
        setCount(count + 1);
        myClass = status ? 'done' : 'todo-item'
      }
      return (
        <>
          <main className={myClass}>
            <input 
              checked={status}
              type="checkbox"
              onChange={checkBoxOnChange}
              id="todo-item-status"
            />
            <p>{`${status}`}</p>
            <p>{taskName}</p>
            <p>{count}</p>
          </main>
        </>
      );
    }
    
    export default TodoItem;
    

    This will render the style properly as it gets updated correctly on onChange event.

    Login or Signup to reply.
  3. Your component is not updating the myClass variable when the checkbox is checked. This is because you are directly assigning the statusInit value to myClass during initialization, and later changing statusInit in the checkBoxOnChange function doesn’t update myClass.

    To fix this, you should use the status state to determine the class dynamically. Here’s the corrected version of your TodoItem component

    import "./TodoItem.css";
    import { useState } from "react";
    
    function TodoItem({ taskName, statusInit }) {
    
      const [status, setStatus] = useState(statusInit);
      const [count, setCount] = useState(0);
     
      function checkBoxOnChange(e) {
        setStatus(e.target.checked);
        setCount(count + 1);
      }
    
      const myClass = status ? 'done' : 'todo-item';
    
      return (
        <>
          <main className={myClass}>
            <input 
              checked={status}
              type="checkbox"
              onChange={checkBoxOnChange}
              id="todo-item-status"
            />
            <p>{`${status}`}</p>
            <p>{taskName}</p>
            <p>{count}</p>
          </main>
        </>
      );
    }
    
    export default TodoItem;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search