React状态已更新但页面未自动渲染,求排查原因
问题:创建新Section后页面无法自动刷新
我查了多篇技术帖子,但现有解决方案都不适用。我的组件通过render方法中的map遍历state里的sections列表渲染内容,这部分功能正常。但通过模态框创建新section并提交后,数据已成功写入数据库,调用getProjectSections方法拉取最新数据并更新state后,state确实包含了新section,可页面就是不自动刷新,必须手动重载页面才能显示新内容。
相关代码如下:
Render方法代码
render() { return ( <ThemeProvider theme={theme}> <Div> <hr /> <div> {this.state.sections.map(section => ( <div className="mb-3" key={section.section_title} > <h3>{section.section_title}</h3> </div> ))} </div> ) }
拉取Section数据的方法
getProjectSections(projId) { fetch(API_URL + `/billingcalculator/sections/distinct/${projId}`) .then((res) => { if (!res.ok) { throw new Error() } return res.json() }) .then((result) => { let listedSections = [...result]; this.setState({ sections: listedSections }); }) .catch((error) => { console.log(error); }) }
创建Section的提交方法
handleSectionCreateSave() { fetch(API_URL + `/billingcalculator/section/create`, { method: "PUT", body: JSON.stringify({ projectId: this.props.billProjId, sectionTitle: this.state.newSectionTitle }), headers: { "Content-Type": "application/json" }, }) .then((res) => { if (!res.ok) { throw new Error(); } return res.json(); }) .then((data) => console.log(data)) .catch((err) => console.log(err)) .then(this.getProjectSections(this.props.billProjId)) .then(this.setState({ showSectionModal: false })) .catch((err) => console.log(err)); }
问题原因分析
Promise链的函数调用错误:
在handleSectionCreateSave里,.then(this.getProjectSections(this.props.billProjId))这行代码是直接执行了getProjectSections函数,而不是把它作为回调传递给then。这会导致拉取数据的操作在创建section的请求还没完成时就触发了,拿到的还是旧数据。异步操作顺序混乱:
直接在then里调用setState({ showSectionModal: false }),没有等待getProjectSections的异步请求和setState完成,虽然state最终会更新,但渲染时机可能被打乱。重复的错误捕获:
第一个.catch会捕获创建请求的错误,但之后的then仍会执行,重复的catch可能掩盖后续操作的问题。
修复方案
修改handleSectionCreateSave的Promise链,确保异步操作按顺序执行:
handleSectionCreateSave() { fetch(API_URL + `/billingcalculator/section/create`, { method: "PUT", body: JSON.stringify({ projectId: this.props.billProjId, sectionTitle: this.state.newSectionTitle }), headers: { "Content-Type": "application/json" }, }) .then((res) => { if (!res.ok) { throw new Error(); } return res.json(); }) .then((data) => { console.log(data); // 用箭头函数确保this指向正确,且等待创建请求完成后再拉取数据 return this.getProjectSections(this.props.billProjId); }) .then(() => { // 等待数据拉取和state更新完成后再关闭模态框 this.setState({ showSectionModal: false }); }) .catch((err) => console.log(err)); }
另外补充两个优化点:
- 把
map中的key从section.section_title改成section的唯一ID(比如数据库主键),避免因标题重复导致React渲染异常。 - 给
getProjectSections添加返回Promise的逻辑,确保后续操作能准确等待它完成:getProjectSections(projId) { return fetch(API_URL + `/billingcalculator/sections/distinct/${projId}`) .then((res) => { if (!res.ok) { throw new Error() } return res.json() }) .then((result) => { let listedSections = [...result]; this.setState({ sections: listedSections }); }) .catch((error) => { console.log(error); }) }
内容的提问来源于stack exchange,提问作者Adam Norton
相关产品推荐
相关产品推荐

