Поиск входных данных для таблицы ANTD

#reactjs #ajax #antd

#reactjs #ajax #antd

Вопрос:

Мне удалось выполнить поисковый ввод, позволяющий выполнять поиск по названию и категории проекта из таблицы antd, но исходные данные {DataSource} не загружаются с данными в dataLog (не уверен, что это из-за запроса AJAX) и, следовательно, не загружаются в таблицу, данные будут толькобудет отображаться при выполнении первого поиска в этом случае, вот мой код:

введите описание изображения здесь

 const ListLogs = () => {
  const [logs, setLogs] = useState([]);
  const [search, setSearch] = useState("");
  // const [latestFive, setLatestFive] = useState([]);
  const [value, setValue] = useState("");
  const timeAgo = (prevDate) => {
    const diff = Number(new Date()) - prevDate;
    const minute = 60 * 1000;
    const hour = minute * 60;
    const day = hour * 24;
    const month = day * 30;
    const year = day * 365;
    switch (true) {
      case diff < minute:
        const seconds = Math.round(diff / 1000);
        return `${seconds} ${seconds > 1 ? "seconds" : "second"} ago`;
      case diff < hour:
        return Math.round(diff / minute)   " minutes ago";
      case diff < day:
        return Math.round(diff / hour)   " hours ago";
      case diff < month:
        return Math.round(diff / day)   " days ago";
      case diff < year:
        return Math.round(diff / month)   " months ago";
      case diff > year:
        return Math.round(diff / year)   " years ago";
      default:
        return "";
    }
  };

  const getAllLogs = async () => {
    try {
      const response = await fetch("http://localhost:5000/logs/");
      const jsonData = await response.json();
      setLogs(jsonData);
    } catch (err) {
      console.error(err.message);
    }
  };

  const expandedRowRender = () => {
    const columns = [
      { title: "Date", dataIndex: "date", key: "date" },
      { title: "Name", dataIndex: "name", key: "name" },
      {
        title: "Status",
        key: "state",
        render: () => (
          <span>
            <Badge status="success" />
            Finished
          </span>
        ),
      },
      { title: "Upgrade Status", dataIndex: "upgradeNum", key: "upgradeNum" },
      {
        title: "Type",
        dataIndex: "operation",
        key: "operation",
        render: () => {
          return (
            <div>
              <Tag color="green">CREATE</Tag>
              <Tag color="gold">UPDATE</Tag>
              <Tag color="red">DELETE</Tag>
            </div>
          );
        },
      },
    ];
    const data = [];
    for (let i = 0; i < 3;   i) {
      data.push({
        key: i,
        date: "2014-12-24 23:12:00",
        name: "This is production name",
        upgradeNum: "Upgraded: 56",
      });
    }
    return <Table columns={columns} dataSource={data} />;
  };

  const dataLog = [];
  for (let i = 0; i < logs.length; i  ) {
    dataLog.push({
      key: i,
      category: <Tag color="default">{logs[i].category}</Tag>,
      title: logs[i].title,
      id: logs[i].id,
      lastUpdated:
        new Date(logs[i].last_updated).toLocaleString()  
        " "  
        timeAgo(new Date(logs[i].last_updated).getTime()),
    });
  }
  const [dataSource, setDataSource] = useState(dataLog);
  console.log("dataSource: ", dataSource);
  console.log("dataLog: ", dataLog);

  const columns = [
    {
      title: "Category",
      dataIndex: "category",
      key: "category",
    },
    {
      title: "Title",
      dataIndex: "title",
      key: "title",
    },
    { title: "ID", dataIndex: "id", key: "id" },
    { title: "Last Updated", dataIndex: "lastUpdated", key: "lastUpdated" },
  ];

  useEffect(() => {
    setDataSource(dataLog);
    getAllLogs();
  }, []);

  return (
    <Fragment>
      <div>
        <header className="headerPage">
          <h1> Logs </h1>
        </header>
      </div>
      <div className="container">
        <Input.Search
          placeholder="Input search text"
          value={value}
          onChange={(e) => {
            const currValue = e.target.value;
            setValue(currValue);
            const filteredData = dataLog.filter(
              (entry) =>
                entry.title.toLowerCase().includes(currValue.toLowerCase()) ||
                entry.category.props.children
                  .toLowerCase()
                  .includes(currValue.toLowerCase())
            );
            console.log("filtered Data: ", filteredData);
            setDataSource(filteredData);
          }}
          // allowClear
          // onChange={(e) => setSearch(e.target.value)}
          // style={{ width: 200, float: "right" }}
        />

        <Table
          bordered
          className="components-table-demo-nested"
          onRow={(i) => ({
            onClick: (e) => {
              history.push(
                `/admin/viewLog/${i.id}/${i.category.props.children}`
              );
            },
          })}
          columns={columns}
          // expandable={{ expandedRowRender }}
          dataSource={dataSource} //tried {dataSource ? dataSource: dataLog} does not work as well
          size="small"
          pagination={false}
        />
      </div>
    </Fragment>
  );
};
export default ListLogs;
  

Пожалуйста, просветите меня для этого! Спасибо

Ответ №1:

Краткий ответ: когда мы вызываем setDataSource(dataLog) внутри useEffect-хуков для первоначального рендеринга (монтирования), который сохранит пустой массив в dataSource переменной, который можно использовать для отображения значка пустого списка или загрузки, нам нужно снова установить источник данных при извлечении данных, чтобы мы могли использовать другой хук useEffect для logs переменной состояния иустановите в нем источник данных.

 useEffect(() => {
    setDataSource(dataLog);
}, [logs]);
  

Подробные сведения:

Чего мы пытаемся достичь с помощью этих перехватов, т.Е. useEffect, так это того, что мы можем написать код, который может реагировать при выполнении определенного действия, например, что мы сделали в useEffect, так это то, что на начальном рендеринге (фаза монтирования) мы устанавливаем пустой массив, а затем вызываем API. После этого, когда поступают данные, мы устанавливаем logs т.е. setLogs(jsonData) .

Который заполнит logs переменную, затем этот цикл вступит в действие и dataLog будет заполнен, но после этого мы никогда не устанавливаем источник данных снова с помощью этого DataLog , т.Е. заполненного списка объектов (мы делали это только в фазе монтирования, в которой dataLog было пусто, или при запуске onChange)

Таким образом, простым решением может быть использование перехватов useEffect для logs переменной, поэтому всякий раз, когда logs переменная изменяется, она также устанавливает источник данных. Как определено выше в кратком ответе.

Таким образом, с помощью этих перехватов мы можем значительно реорганизовать этот код.

Еще одна вещь: я рекомендую использовать getAllLogs функцию с await ключевым словом, которая сделает так, чтобы асинхронный код работал как синхронизация, т.е.

 useEffect(async () => {
    await getAllLogs();
}, []);
  

Я (пытаюсь) воспроизвести его здесь