Отображение списка элементов массива с использованием условия в ReactJS

#reactjs

Вопрос:

Я создал приложение, в котором пользователь может изменять статус задач, а также фильтровать задачи.

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

export default function App() {
  const todos = [
    {
      title: "test",
      id: 1,
      done: false
    },
    {
      title: "test2",
      id: 2,
      done: true
    }
  ];
  const [myTodo, setMyTodo] = useState(todos);

  const changeStatus = (e, id) => {
    console.log(e.target.value, id);
    const newValues = todos.map((i) => {
      if (id === i.id) {
        return {
          ...i,
          done: e.target.value === "false" ? true : false
        };
      }
      return i;
    });
    setMyTodo(newValues);
  };

  const filterDone = () => {
    const r = myTodo.filter((i) => i.done === true);
    setMyTodo(r);
  };

  const filterActive = () => {
    const r = myTodo.filter((i) => i.done === false);
    setMyTodo(r);
  };

  const filterAll = () => {
    setMyTodo(myTodo);
  };
  return (
    <div className="App">
      <button onClick={filterAll}>Filter By all</button>
      <button onClick={filterDone}>Filter By donne</button>
      <button onClick={filterActive}>Filter By active</button>

      {myTodo.map((t) => {
        return (
          <div>
            {t.title}
            <select onChange={(e) => changeStatus(e, t.id)} name="status">
              <option hidden>status</option>
              <option value="false">Done</option>
              <option value="true">Active</option>
            </select>
            {t.done ? "done" : "active"}
          </div>
        );
      })}
    </div>
  );
} 

Теперь, когда я пытаюсь отфильтровать, я не получаю ожидаемого результата. Нажимая несколько раз на разные кнопки, я ничего не получаю в качестве результатов. Как изменить код, чтобы можно было отфильтровать список заданий с учетом того, что пользователь может изменять статус каждого задания?
демо:https://codesandbox.io/s/восхищение-гром-jywy6?файл=/src/App.js:0-1506

Ответ №1:

Когда вы устанавливаете новое состояние с отфильтрованной информацией, ваши исходные данные исчезают, в основном удаляются. Вместо этого вы должны фильтровать данные только там, где они вам нужны, без установки какого-либо нового состояния. Таким образом, задачи в представлении фильтруются, но у вас все еще есть все задачи в состоянии.

 export default function App() {
  const todos = [
    {
      title: "test",
      id: 1,
      done: false
    },
    {
      title: "test2",
      id: 2,
      done: true
    }
  ];
  const [myTodo, setMyTodo] = useState(todos);
  const [filter, setFilter] = useState(null);
 
  ...

  const filterDone = () => {
    setFilter("done");
  };

  const filterActive = () => {
    setFilter("active");
  };

  const filterAll = () => {
    setFilter(null);
  };

  return (
    <div className="App">
      <button onClick={filterAll}>Filter By all</button>
      <button onClick={filterDone}>Filter By donne</button>
      <button onClick={filterActive}>Filter By active</button>

      {myTodo
        .filter((t) => {
          if (filter === "done") return t.done === true;
          if (filter === "active") return t.done === false;
          return true;
        })
        .map((t) => {
          return (
            <div>
              {t.title}
              <select onChange={(e) => changeStatus(e, t.id)} name="status">
                <option hidden>status</option>
                <option value="false">Done</option>
                <option value="true">Active</option>
              </select>
              {t.done ? "done" : "active"}
            </div>
          );
        })}
    </div>
  );
}

 

песочница: https://codesandbox.io/s/flamboyant-pond-3qmsq?file=/src/App.js