javascriptreactjstypescriptreact-hooksreact-usememo

React Typescript: How do I useMemo for a checkbox value?


I'm currently working on a to do list project using React and Typescript. Right now I am able to add a new to do item using a form and delete each to do item. Each to do item has a checkbox with a boolean value. What I would like to do is filter each to do item as "Done" when I click on the checkbox.

I have a Done (const DoneTasks) button on my page. Once it is clicked a copy of my App appears. Within the html components I want all my checked to do items to be stored on this page and filter out of the default App page.

I believe I have to useMemo for checked value, but I am not sure where to use it?

CODE SANDBOX: https://codesandbox.io/s/to-do-list-mkr29l

App.tsx

To Do Item Interface

interface ToDo {
  title: string;
  priority: 1 | 2;
  description: string;
  checked: true | false;
}

To Do Item function with checkbox prop

function ToDoItem(props: {
onCheckBoxCheck: any;}) 

{const checkBoxCheck = (event: any) => {
const checkBox = event.currentTarget.checked;
const newCheckBoxValue = checkBox;
console.log(checkBox);
props.onCheckBoxCheck(newCheckBoxValue);
};

  return (
    <div
      className="to-do-item"
      data-priority={props.toDo.priority}
      id="to-do-item">
      <div className="checkbox-title-container">
        <div className="check-title-div">
          <div>
            <input
              type="checkbox"
              id="checkbox"
              onChange={checkBoxCheck}
              checked={props.toDo.checked}
            />
          </div>
    </div>
  );
}

const initialTodosString = localStorage.getItem("toDoList");

const initialTodos = initialTodosString
  ? JSON.parse(initialTodosString)
  : [myToDo1, myToDo2];

App function with hooks, I think I should add useMemo in here?

function App(): JSX.Element {
  const [toDos, setToDos] = useState<ToDo[]>(initialTodos);
  const [addingToDo, setAddingToDo] = useState(false);
  const [showingDoneTasks, setShowDoneTasks] = useState(false);


  // Do I add useMemo here for checked value?


  useEffect(
    function () {
      localStorage.setItem("toDoList", JSON.stringify(toDos));
    },
    [toDos]
  );

showDone function

function showDone()
{setShowDoneTasks(true)}

//Done tasks function that returns html elements (I have included buttons in here)

const DoneTasks = () => (
        </div>
        <div className="status-container">
          <button className="activeButton">Active</button>
          <button className="doneButton" onClick={showDone}>Done
          </button>
        </div>
         </div>    
 );

if(showingDoneTasks){
  return <DoneTasks  />
};

App components (I kept buttons with To Do items and checkbox function below)

  return (
    <div className="App">
        <div className="status-container">
          <button className="activeButton">Active</button>
          <button className="doneButton" onClick={showDone}>Done
          </button>
        </div>
      </div>
    
      {toDos.map((toDoItem: ToDo) => (
        <ToDoItem
          onDeleteToDo={function () {
            const updatedToDos = toDos.filter((x) => x !== toDoItem);
            setToDos(updatedToDos);
            
          }}

          onCheckBoxCheck={function(checked: true | false) {
            const updatedToDos = toDos.map((x) =>
            x === toDoItem ? ({ ...x, checked } as any) : x,
          );
          setToDos(updatedToDos);}}

Solution

  • It's hard to read the code above, but you created multiple states/components to track down the filtered todos.

    Regarding your question about memos, you're right; that's where you need to add the memo since it's the parent component that "holds" your todos state.

    But, I would like to add some points to your implementation and make it more readable and easy to manage. Others may have different opinions, but I want to share my thoughts.

    Process:

    1. Create a "todos" state that manages the display of the Todo items. You can filter the display based on statuses like "done" or "not done."

      • With this implementation, you only have a single state to manage, and it's more predictable where to debug if the display is wrong
    2. Create a useRef that holds the initial state of the todos. This will be used to display if no status filter is made. This also helps prevent the component from being re-render when modified. Of course, you can use the useEffect when the .ref as a dependency when you want to save the updated the todos value.

    Please let me know if it still needs to be clarified. I'd be happy to help.

    Take note:

    Reference: https://kentcdodds.com/blog/usememo-and-usecallback