javascript - React 状态在渲染方法和页面上实际显示的内容之间不同步
问题描述
我需要访问我的 React 应用程序之外的 DOM 元素,它的加载速度可能比我的应用程序慢。然后我需要更新我的状态来渲染一些不同的东西。为此,我使用从 componentDidMount() 启动的递归函数轮询 DOM 元素。我看到一个奇怪的问题,一旦找到元素并且我更新了状态,事情就会不同步。在渲染函数中,我的 console.log() 显示了更新后的状态值,在 React 开发者工具中我看到了更新后的状态值,但在实际渲染的页面上,我看到的仍然是旧的状态值。
代码:
// initially doesn't exist. Added to the DOM after 3 seconds
let slowElement = document.querySelector('.external-dom-element')
class App extends React.Component {
constructor (props) {
super(props)
this.state = {
showFoundSlowElementMessage: false,
slowElementCheckMaxAttempts: 5,
slowElementCheckCount: 0,
}
this.checkForSlowElement = this.checkForSlowElement.bind(this)
}
componentDidMount () {
this.checkForSlowElement()
}
checkForSlowElement () {
slowElement = document.querySelector('.external-dom-element')
if (slowElement !== null) {
console.log('found') // element found, show message
this.setState({
showFoundSlowElementMessage: true
})
} else {
console.log('not found') // element not found, increment count and check again after delay
this.setState({
slowElementCheckCount: this.state.slowElementCheckCount + 1
}, () => {
if (this.state.slowElementCheckCount < this.state.slowElementCheckMaxAttempts) {
window.setTimeout(this.checkForSlowElement, 1000)
}
})
}
}
render() {
const foundSlowElement = this.state.showFoundSlowElementMessage
? <p>Found slow element</p>
: <p>No sign of slow element, checked {this.state.slowElementCheckCount} times</p>
// null until it is added to the page
console.log(foundSlowElement)
return (
<div>
<h1>Hello</h1>
{foundSlowElement}
</div>
);
}
}
}
ReactDOM.render(<App />, document.getElementById('react-target'));
// Simulate slow element by adding it to the DOM after 3 seconds
window.setTimeout(() => {
const root = document.getElementById('root');
const newElement = '<div class="external-dom-element">slow element</div>';
root.innerHTML += newElement;
}, 3000)
解决方案
我自己想通了。它与我的组件无关,破坏它的是演示本身。当我通过附加根元素的内部 html 来模拟慢速元素时:
root.innerHTML += newElement;
它重新解析整个元素并且 React 丢失了它之前设置的所有事件处理程序等。
推荐阅读
- excel - rng.RefersToRange.Parent.Name 和 rng.Parent.Name 之间的区别
- kubernetes - Kong-ingress-controller CrashLoopBackOff : "kong-proxy" 被禁止
- jquery - 使用 Stackable.js 的表过滤器 - (如何复制数据属性?)
- tsql - 循环遍历表,同时记录不断添加到表中
- python-3.x - 用高斯预测 MNIST 数据集中的类——不同参数的相同预测误差?
- python - 如何在python中获取浮动文本文件?
- node.js - 一些请求没有进入节点服务器
- influxdb - HAproxy 为每个服务器单独的授权标头
- php - PHP语言中的“?array”是什么意思?
- php - 禁用日期选择器中已保存在 mysql 数据库中的日期