1

I'm building a Todo App with React and almost everything worked fine. The todo-items have a "completed" property and based on the property I want to filter todos. ( When you click on an item the "completed" property changes from false to true ).

This is how it looks like. But I kinda don't know how to implement it.


const ACTIONS = {
  ADD_TODO: "add-todo",
  CLEAR_TODO: "clear-todo",
  SWITCH_TODO_TYPE: "switch-todo-type",
};

const todosInitalState = {
  todos: [
   {todoValue: "exampleTodo", id: 3.14, completed: false},
   {todoValue: "exampleTodoNo2", id: 42, completed: true}
  ],
  activeTodos: [
   {todoValue: "exampleTodo", id: 3.14, completed: false},
  ],
  completedTodos: [
   {todoValue: "exampleTodoNo2", id: 42, completed: true}
  ],
};
export default function TodosState() {
  const [todosState, dispatchTodos] = useReducer(
    todosReducer,
    todosInitalState
  );

  const uncheckedTodos = todosState.todos.filter(
    (todo) => todo.completed === false
  );

  return (
    <div className={styles["todos-container"]}>
      <h1>Todo</h1>
      <Input onAddTodo={storeTodoValue}></Input>
      <ul>
        {todosState.todos.map((todo) => { // `**HOW CAN I NOW SHOW THE STATE BASED ON THE CLICKED BUTTON** `
          return (
            <TodoItem
              key={todo.id}
              id={todo.id}
              text={todo.todoValue}
              onCheck={saveCheckedValues}
            ></TodoItem>
          );
        })}
      </ul>
      <div className={styles["todos-container__bottom"]}>
        <span>{uncheckedTodos.length} tasks left</span>
        <div className={styles.buttons}>
          <button>All</button>
          <button>Active</button>
          <button>Completed</button>
        </div>
        <button onClick={deleteCheckedTodos}>Clear Completed</button>
      </div>
    </div>
  );
}

I got the filter logic already done. So it's just about how i can render the right state based on the button. Any tips how i can achieve that? :)

ignacio
  • 1,181
  • 2
  • 15
  • 28
Ayhan
  • 51
  • 5

1 Answers1

0

You could define an auxiliary filteredTodo state to store the filtered todos.
Then, declare a filterTodos function to filter the list based on the clicked button:

const ACTIONS = {
  ADD_TODO: 'add-todo',
  CLEAR_TODO: 'clear-todo',
  SWITCH_TODO_TYPE: 'switch-todo-type',
};

const todosInitalState = {
  todos: [
    { todoValue: 'exampleTodo', id: 3.14, completed: false },
    { todoValue: 'exampleTodoNo2', id: 42, completed: true },
  ],
  activeTodos: [{ todoValue: 'exampleTodo', id: 3.14, completed: false }],
  completedTodos: [{ todoValue: 'exampleTodoNo2', id: 42, completed: true }],
};
export default function TodosState() {
  const [todosState, dispatchTodos] = useReducer(
    todosReducer,
    todosInitalState
  );

  const uncheckedTodos = todosState.todos.filter(
    (todo) => todo.completed === false
  );

  const filterTodos = (state) => {
    switch (state) {
      case 'All':
        setFilteredTodo([...todosState.todos]);
        break;
      case 'Active':
        setFilteredTodo(
          [...todosState.todos].filter((todo) => todo.completed === false)
        );
        break;
      case 'Completed':
        setFilteredTodo(
          [...todosState.todos].filter((todo) => todo.completed === true)
        );
        break;
      default:
        break;
    }
  };

  const [filteredTodo, setFilteredTodo] = useState([...todosState.todos]);

  return (
    <div className={styles['todos-container']}>
      <h1>Todo</h1>
      <Input onAddTodo={storeTodoValue}></Input>
      <ul>
        {filteredTodo.map((todo) => {
          return (
            <TodoItem
              key={todo.id}
              id={todo.id}
              text={todo.todoValue}
              onCheck={saveCheckedValues}
            ></TodoItem>
          );
        })}
      </ul>
      <div className={styles['todos-container__bottom']}>
        <span>{uncheckedTodos.length} tasks left</span>
        <div className={styles.buttons}>
          <button onClick={() => filterTodos('All')}>All</button>
          <button onClick={() => filterTodos('Active')}>Active</button>
          <button onClick={() => filterTodos('Completed')}>Completed</button>
        </div>
        <button onClick={deleteCheckedTodos}>Clear Completed</button>
      </div>
    </div>
  );
}
```
lpizzinidev
  • 12,741
  • 2
  • 10
  • 29
  • I mean it works but now my todos are only loading when clicking on the buttons and not when the page reloads. But thank you though :) – Ayhan Mar 19 '22 at 20:36