在 React 中更新后无法重新渲染
Posted
技术标签:
【中文标题】在 React 中更新后无法重新渲染【英文标题】:Can't re-render after update in React 【发布时间】:2016-12-11 01:03:33 【问题描述】:我在 React 中有一个简单的数据库,其中通过 Ajax 处理对数据库的更新和删除。
在记录组件上成功调用 Ajax 后,更新或删除的记录被传递给记录组件,记录组件显示所有记录。
下面的处理方法会更新记录的状态并重新渲染结果。
我的问题是,虽然 handleDelete 方法工作正常(并且在没有删除记录的情况下重新呈现记录),但 handleUpdate 方法却没有,并且会保留未更新的记录,直到我刷新页面。
知道为什么 handleUpdate 中的 setState 不会重新渲染结果吗?
下面是代码:
class Sites extends React.Component
constructor (props)
super(props);
this.handleUpdate = this.handleUpdate.bind(this);
this.handleDelete = this.handleDelete.bind(this);
this.state = records: this.props.records;
handleUpdate (record)
let records = this.state.records;
let index = records.map((x) => return x.id).indexOf(record.id);
records.splice(index, 1, record);
this.setState(records: records); # this doesn't re-render the results
handleDelete (record)
let records = this.state.records;
let index = records.map((x) => return x.id).indexOf(record.id);
records.splice(index, 1);
this.setState(records: records); # this re-renders the results
render ()
let records = this.state.records.map((record) =>
return (
<Record record=record key=record.id handleUpdateRecord=this.handleUpdate handleDeleteRecord=this.handleDelete/>
);
);
return (
<div className="col-sm-9">
<table className="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>City</th>
<th>State</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
records
</tbody>
</table>
</div>
);
【问题讨论】:
你能提供<Record />
的实现吗?
你不应该通过splice
改变状态。您需要添加let records = this.state.records.slice();
。你记录了句柄更新吗?
【参考方案1】:
您应该始终将状态视为不可变,并且永远不要直接修改它。复制其内容,修改副本并重新设置。
我准备了一支笔,我为您的<Record />
即兴实现并重写了onUpdate
和onDelete
逻辑,将状态视为不可变,通过映射或过滤创建一个新的records
数组旧的并重新设置。看到它here。我已经重命名了一些东西,但大部分都是一样的!
这些是重要的部分:
handleUpdate (record)
const records = this.state.records.map(r =>
if (r.id !== record.id) return r;
return record;
)
this.setState(records)
我们收到更新的记录并映射旧数组:如果我们找到与新元素相同id
的元素,则返回后者,否则返回原始元素。 map
返回一个新数组,所以我们是安全的。
handleDelete (id)
const records = this.state.records.filter(r => r.id !== id)
this.setState(records)
这里我们只需要 id,并根据状态过滤 records
数组,留下我们要删除的带有 id
的元素。同样,filter
返回一个新数组,所以我们很好。
希望这会有所帮助!
【讨论】:
这非常有帮助!非常感谢您抽出宝贵时间提供帮助! 这太奇怪了,但在 setState 调用后我仍然无法重新渲染更新。我将包括下面的代码。任何想法为什么这不起作用?handleUpdate (site) const sites = this.state.sites.map(s => if (s.id !== site.id) return s; return site; ); this.setState(sites); console.log(sites);
正确更新的站点列表被记录到控制台,但 React 不会重新渲染显示的更新列表。【参考方案2】:
一个简单的
componentWillReceiveProps()
收到道具时触发,并将使用更新后的状态。
【讨论】:
以上是关于在 React 中更新后无法重新渲染的主要内容,如果未能解决你的问题,请参考以下文章
在使用数据库数据更新上下文后,React 'useContext' 钩子不会重新渲染