【发布时间】:2022-01-16 20:03:06
【问题描述】:
我知道这个问题已经被问过很多次了,我也知道useCallback 是如何工作的,但是我的问题与antd UI 框架有关(或者也许没关系)。我做了一个最小的、可重现的例子:
import React, { useState, useCallback } from "react";
import ReactDOM from "react-dom";
import { Form, Input, Button, Table } from "antd";
import faker from "faker";
const mockApi = {
async getUsers({ country, current, pageSize }) {
return {
total: 100,
users: Array.from({ length: 10 }).map((_) => ({
id: faker.random.uuid(),
email: faker.internet.email(),
country: "US"
}))
};
}
};
const initialPagination = { current: 1, pageSize: 10 };
function App() {
const [form] = Form.useForm();
const [pagination, setPagination] = useState(initialPagination);
const [users, setUsers] = useState([]);
const [total, setTotal] = useState(0);
useMemo(() => {
console.log("render pagination: ", pagination);
}, [pagination]);
const getUsers = useCallback(async () => {
console.log("getUsers pagination: ", pagination);
const params = {
...pagination,
country: form.getFieldValue("country")
};
const getUsersResponse = await mockApi.getUsers(params);
setUsers(getUsersResponse.users);
setTotal(getUsersResponse.total);
}, [pagination]);
const onPageChanged = useCallback(
(current) => {
console.log("change current page to: ", current);
setPagination({ ...pagination, current });
getUsers();
},
[pagination, getUsers]
);
return (
<div>
<h1>Test</h1>
<Form form={form} initialValues={{ email: "" }} onFinish={getUsers}>
<Form.Item name="country" label="country">
<Input type="text" />
</Form.Item>
<Form.Item>
<Button htmlType="submit">submit</Button>
</Form.Item>
</Form>
<Table
pagination={{ ...pagination, onChange: onPageChanged, total }}
dataSource={users}
columns={[{ title: "email", dataIndex: "email" }]}
rowKey="id"
/>
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
第 1 步:提交表单
第 2 步:将当前页面更改为 2。
第 3 步:将当前页面更改为 3。
日志:
render pagination: {current: 1, pageSize: 10}
getUsers pagination: {current: 1, pageSize: 10}
change current page to: 2
getUsers pagination: {current: 1, pageSize: 10}
render pagination: {current: 2, pageSize: 10}
change current page to: 3
getUsers pagination: {current: 2, pageSize: 10}
render pagination: {current: 3, pageSize: 10}
getUsers函数中pagiation.current的值不是最新的值。它始终是以前的值。我使用pagination 作为getUsers 函数的依赖项。所以我认为当onPageChanged事件处理函数被触发时,设置新的分页状态后,getUsers()函数应该用deps的最新值重新创建。
我有点不知道为什么。我知道我可以使用useState 的functional updates 而不是useCallback + deps。但是我坚持使用useCallback+deps的方式。
【问题讨论】:
-
getUsersinonPageChanged将始终是在当前闭包中创建的那个,并且不能通过状态更新来更改。你的问题与这个问题基本相同:stackoverflow.com/questions/54069253/… 这不是 antd 或 react,它是普通的 javascript 闭包。
标签: reactjs react-hooks antd