我有一个如下所示的组件(是的,我知道存在React .)。我也创建了一个CodeSandbox示例。
export class App extends React.Component {
state = {
loadingStatus: "idle"
};
componentDidMount() {
debugger;
setTimeout(() => {
this.setState({ loadingStatus: "loading" });
}, 1);
setInterval(() => {
const loadingStatus =
this.state.loadingStatus === "loading" ? "complete" : "loading";
this.setState({ loadingStatus });
}, 3000);
}
render() {
const { loadingStatus } = this.state;
return (
<div>
<div>loadingStatus: {this.state.loadingStatus}</div>
<div role="status">
{loadingStatus === "loading" && (
<img
alt="loading"
src="https://upload.wikimedia.org/wikipedia/commons/b/b1/Loading_icon.gif?20151024034921"
/>
)}
{loadingStatus === "complete" && (
<span className="visually-hidden">Loading has completed</span>
)}
</div>
{loadingStatus === "complete" && (
<div>Content has loaded. The page will reload again momentarily.</div>
)}
</div>
);
}
}
此组件演示如何使页面加载指示符可供屏幕阅读器用户访问。关键是在role="status"
中使用一个元素,当它的内容发生变化时,它会宣布。它需要包括:
我遇到的问题是,当我在componentDidMount中将加载状态从“空闲”更改为“加载”时,它不会在DOM中“注册”,除非我将其包装在setTimeout()中,甚至只是延迟了1ms。如果我没有setTimeout(),则不会公布role="status"
元素中的内容更改。
有趣的是,如果在浏览器中删除setTimeout()并打开dev工具,debugger;
就会中断,当状态为“空闲”时,您可以看到UI是呈现的。这使我感到困惑,为什么有必要拖延。
需要明确的是,问题是,如果没有setTimeout(),“加载”的初始宣布就不会发生。你需要一个屏幕阅读器。)测试.
提前谢谢。
发布于 2022-05-20 19:53:06
在呈现组件之后,componentDidMount
方法被称为。这就是为什么在添加调试器语句时可以看到它的原因。
然后,在componentDidMount
中调用componentDidMount
实际上将触发对render
的第二次调用。它读取新状态并更新DOM。
我不知道为什么要使用setInterval
,但是如果简化示例,它的工作方式实际上是您所期望的。
componentDidMount() {
this.setState({ loadingStatus: 'loading' });
setTimeout(() => {
this.setState({ loadingStatus: 'complete' });
}, 3000);
}
这会导致以下流:
在上面的示例中,setTimeout(..., 3000)
表示一个模拟的API调用。您很可能希望执行异步操作,而不是如下所示:
componentDidMount() {
this.setState({ loadingStatus: 'loading' });
fetch('/your/api/endpoint').then(response => {
// do something with the response
this.setState({ loadingStatus: 'complete' });
});
}
如果在尝试上述方法后仍有问题,可能是因为如果setState是异步的和您所做的更改发生在一个连续的执行流中,则可以批处理它们。将代码包装在requestAnimationFrame
回调中将确保在更新状态之前完成上一次呈现。
componentDidMount() {
requestAnimationFrame(() => {
this.setState({ loadingStatus: 'loading' });
fetch('/your/api/endpoint').then(response => {
// do something with the response
this.setState({ loadingStatus: 'complete' });
});
});
}
https://stackoverflow.com/questions/72292842
复制相似问题