将按钮渲染为加载登录React



描述:

我在表单中有一个按钮。单击该按钮后,表单将提交到后端。当请求在飞行中时,我希望按钮显示装载信号,而不是通常的文本。请求完成后,我希望表单消失。

我可以使用useState为不同的按钮表单执行此操作,但我的问题是,就在表单消失之前,文本再次显示。这是一个小问题,但看起来没有经过处理。

问题:

单击该按钮后,加载动画将按预期显示。当请求完成时,我可以看到文本在对话框消失前重新出现一秒钟。在重新打开对话框之前,我不希望文本再次出现。

我尝试了什么:

在调用(并等待)关闭对话框后,我当前将加载状态更改回false。我试着不这么做,但这会导致当我重新打开对话框时加载按钮在那里,这更糟。

为了纠正这一点,我尝试在启动时将加载状态的值设置为false,如下所示:

useEffect(() => {
setLoading(false);
}, []);

这没有任何影响,这让我相信组件只安装了一次,当我关闭它时,它实际上并没有被卸载。

我尝试使用material-ui/lab中的LoadingButton组件,但由于各种类型脚本/反应的原因,它只是左右抛出错误。由于这是一个实验包,我决定远离它

代码:

这是我的组件:

export const NewClientDialog = (props: INewClientDialogProps) => {
// open is a boolean that's true when the dialog is open, close is a function that closes the form dialog
const {open, close} = props;
const [fn, setFn] = useState("");
const [ln, setLn] = useState("");
const [email, setEmail] = useState("");
const [pn, setPn] = useState("");
const [newUser, setNewUser] = useState<INewClientProps>();
const [loading, setLoading] = useState(false);
// this is not optimal, but not the point of this post. It sets the object from the form inputs for the network request
useEffect(() => {
const newClient: INewClientProps = {
firstName: fn,
lastName: ln,
email: email,
phoneNumber: pn
}
setNewUser(newClient)
}, [fn, ln, email, pn])

// this gets triggered when a button is clicked
const onAddClient = () => {
// set the loading animation
setLoading(true)
// this calls the network API and returns a promise
createNewClient(newUser)
// once the promise is completed, close the dialog
.then(() => close())
// then set the loading back to false
.then(() => setLoading(false))
}
// this the button, if loading is true then it is a circular loading icon otherwise it's text
const AddClientButton = () => {
const contents = loading ? ><CircularProgress /> : <div>Create new client</div>
return (
<Button onClick={() => onAddClient()}>
{contents}
</Button>
);
}
return (
<div>
<Dialog onClose={close} open={open}>
<TextField label="First name" onChange={(value) => setFn(value.target.value)}/>
<TextField label="Last name" onChange={(value) => setLn(value.target.value)}/>
<TextField label="Email address" onChange={(value) => setEmail(value.target.value)}/>
<TextField label="Phone number" onChange={(value) => setPn(value.target.value)}/>
<AddClientButton />
</Dialog>
</div>
)
}

刚写完,我就顿悟了:

useEffect(() => {
setLoading(false);
}, [open]);

这正是我希望它做的事情——当对话框打开时,将loading设置为false。我删除了onAddClient中的setLoading(false)调用。

我将不谈这个,希望它能帮助任何想在Material UI中创建动态按钮的人。

最新更新