#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();
}, []);
Я (пытаюсь) воспроизвести его здесь