reactjs - 在异步函数中使用 React useState 钩子更新函数
问题描述
尝试 setState 似乎不会立即更新状态,我不确定如何达到预期的结果。
const Settings = (props: Props) => {
const { user } = props;
const initState: State = {
newName: user.displayName,
newAvatarUrl: user.avatarUrl,
disabled: false,
};
const [form, setForm] = useState(initState);
const handleUploadFile = async () => {
const fileElement = document.getElementById('upload-file') as HTMLFormElement;
const file = fileElement.files[0];
if (file == null) {
return;
}
setForm({ ...form, disabled: true });
try {
const response = await asynFunc1()
await asyncFun2(response)
setForm({ ...form, newAvatarUrl: response.url });
await asyncFunc3(form.newAvatarUrl) // Expected: response.url Observed: old value
} catch (error) {
consol.log(error)
} finally {
setForm({ ...form, disabled: false });
}
};
return (
<h4>Your Avatar</h4>
<Avatar
src={form.newAvatarUrl}
style={{
display: 'inline-flex',
verticalAlign: 'middle',
marginRight: 20,
width: 60,
height: 60,
}}
/>
<label htmlFor="upload-file">
<Button variant="outlined" color="primary" component="span" disabled={form.disabled}>
Update Avatar
</Button>
</label>
<input
accept="image/*"
name="upload-file"
id="upload-file"
type="file"
style={{ display: 'none' }}
onChange={handleUploadFile}
/>
);
};
看起来 setForm 不是同步的,但它不返回承诺,所以我不确定如何以同步方式使用它。
解决方案
正如评论中提到的,状态更新是异步的。相反,您应该将 response.url 传递给 asyncFunc3 调用,并在成功返回后设置您的表单状态。会是这样的:
const Settings = (props: Props) => {
const { user } = props;
const initState: State = {
newName: user.displayName,
newAvatarUrl: user.avatarUrl,
disabled: false,
};
const [form, setForm] = useState(initState);
const handleUploadFile = async () => {
const fileElement = document.getElementById('upload-file') as HTMLFormElement;
const file = fileElement.files[0];
if (file == null) {
return;
}
setForm({ ...form, disabled: true });
try {
const response = await asynFunc1()
await asyncFun2(response)
await asyncFunc3(response.url)
setForm({ ...form, newAvatarUrl: response.url });
} catch (error) {
consol.log(error)
} finally {
setForm({ ...form, disabled: false });
}
};
return (
<h4>Your Avatar</h4>
<Avatar
src={form.newAvatarUrl}
style={{
display: 'inline-flex',
verticalAlign: 'middle',
marginRight: 20,
width: 60,
height: 60,
}}
/>
<label htmlFor="upload-file">
<Button variant="outlined" color="primary" component="span" disabled={form.disabled}>
Update Avatar
</Button>
</label>
<input
accept="image/*"
name="upload-file"
id="upload-file"
type="file"
style={{ display: 'none' }}
onChange={handleUploadFile}
/>
);
};
推荐阅读
- c++ - 如何使用 GLFWwindow 指针获取 HWND?
- node.js - 使用knex查找数据节点js
- c++ - 如何将委托^传递给c ++ / cli中的本机类
- android - 我想获取 json 数据的布尔“状态”的值,并根据 kotlin 中的值执行一些操作
- python - 二进制分类的损失没有减少
- python - 数据帧行的快速笛卡尔总和
- bash - 将 BASH 脚本转换为在 SH 上运行(通过 BusyBox)
- java - Payara 5.2020.4 未启动
- java - 从 Spring Security 过滤器返回自定义 http 错误消息
- css - Inline CSS looks different when looping through