Reactjs 在异步函数中使用React-useState钩子更新函数
尝试设置状态似乎不会立即更新状态,我不确定如何达到预期的结果Reactjs 在异步函数中使用React-useState钩子更新函数,reactjs,react-hooks,Reactjs,React Hooks,尝试设置状态似乎不会立即更新状态,我不确定如何达到预期的结果 const Settings = (props: Props) => { const { user } = props; const initState: State = { newName: user.displayName, newAvatarUrl: user.avatarUrl, disabled: false, }; c
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}
/>
);
};
const设置=(道具:道具)=>{
const{user}=props;
常量initState:状态={
newName:user.displayName,
newAvatarUrl:user.avatarUrl,
残疾人士:错,,
};
const[form,setForm]=useState(initState);
const handleUploadFile=async()=>{
const fileElement=document.getElementById('upload-file'),作为HTMLFormElement;
const file=fileElement.files[0];
if(file==null){
返回;
}
setForm({…form,disabled:true});
试一试{
const response=wait asynFunc1()
等待asyncFun2(响应)
setForm({…form,newAvatarUrl:response.url});
wait asyncFunc3(form.newAvatarUrl)//预期:response.url观察到:旧值
}捕获(错误){
控制台日志(错误)
}最后{
setForm({…form,disabled:false});
}
};
返回(
你的化身
更新头像
);
};
看起来setForm不是同步的,但它不返回承诺,因此我不确定如何以同步方式使用它。如注释中所述,状态更新是异步的。相反,您应该将response.url传递给asyncFunc3调用,并在成功返回后设置表单状态。大概是这样的:
const设置=(道具:道具)=>{
const{user}=props;
常量initState:状态={
newName:user.displayName,
newAvatarUrl:user.avatarUrl,
残疾人士:错,,
};
const[form,setForm]=useState(initState);
const handleUploadFile=async()=>{
const fileElement=document.getElementById('upload-file'),作为HTMLFormElement;
const file=fileElement.files[0];
if(file==null){
返回;
}
setForm({…form,disabled:true});
试一试{
const response=wait asynFunc1()
等待asyncFun2(响应)
等待asyncFunc3(response.url)
setForm({…form,newAvatarUrl:response.url});
}捕获(错误){
控制台日志(错误)
}最后{
setForm({…form,disabled:false});
}
};
返回(
你的化身
更新头像
);
};
状态以异步方式更新。调用函数更新状态后,无法立即记录更新状态。组件必须重新渲染才能看到更新的状态。更新状态后,您可以使用useffect
hook执行任何代码。@Yousaf谢谢。我更改了函数调用以使用所需的值,而不依赖于状态。视图仍然没有反映更新的状态,这意味着状态实际上没有更新,对吗?谢谢,这确实是我必须做的,以使逻辑正确。视图仍不反映更新的状态。我的印象是,更改状态会触发重新渲染,但我不确定如何以编程方式触发。可能是用户道具也正在更新,而整个内容都会重新渲染?如果没有更多的信息,我真的说不出来。也许你可以举一个关于感谢维克多的小例子。在键入一个示例时,我意识到是最后一个块过度编写了更新。你知道我怎样才能改变状态,就像最终的工作方式一样吗?是的,当你按照你在那里做的方式来解构状态对象时,你就是在解构你的初始状态(因此在某种竞争条件下过度写入)。请改为尝试执行此操作。setState(prevState=>({…prevState,flag:false});
通过传递函数,您将获得状态“frame”,并且不会使用过时的状态对象。谢谢Viktor。