【问题标题】:Search Input for ANTD Table搜索 ANTD 表的输入
【发布时间】:2020-11-07 00:52:18
【问题描述】:

我已经设法进行了一个搜索输入,允许从 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;

请赐教!谢谢

【问题讨论】:

    标签: reactjs ajax antd


    【解决方案1】:

    简答: 当我们在 useEffect 钩子中调用 setDataSource(dataLog) 进行初始渲染(安装)时,会将空数组保存在 dataSource 变量中,该变量可用于显示空列表图标或加载,我们必须设置获取数据时再次数据源,因此,我们可以为logs状态变量使用另一个useEffect钩子并在其中设置数据源。

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

    详情
    我们试图用这些钩子(即useEffect)实现的是,我们可以编写一个代码,当定义的动作发生时做出反应,例如我们在 useEffect 中所做的是,在初始渲染(安装阶段)时,我们设置空数组,然后调用 API。之后,当数据到达时,我们设置logs,即setLogs(jsonData)
    它将填充logs 变量,然后该循环开始发挥作用,dataLog 将被填充,但之后我们再也没有使用此DataLog 再次设置数据源,即填充的对象列表(我们只是这样做了在 dataLog 为空的挂载阶段,或者当 onChange 被触发时)
    因此,一个简单的解决方案可以是对logs 变量使用useEffect 挂钩,这样,每当logs 变量发生变化时,它也会设置数据源。如上所定义的简短回答。
    因此,通过这些钩子,我们可以显着重构这段代码。

    还有一件事: 我建议使用 getAllLogs 函数和 await 关键字,这将使异步代码像同步代码一样工作,即

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

    我(尝试)复制它here

    【讨论】:

      猜你喜欢
      • 2021-06-15
      • 1970-01-01
      • 2020-10-18
      • 2019-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多