在 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>
    );
   
  

【问题讨论】:

你能提供&lt;Record /&gt;的实现吗? 你不应该通过splice改变状态。您需要添加let records = this.state.records.slice();。你记录了句柄更新吗? 【参考方案1】:

您应该始终将状态视为不可变,并且永远不要直接修改它。复制其内容,修改副本并重新设置。

我准备了一支笔,我为您的&lt;Record /&gt; 即兴实现并重写了onUpdateonDelete 逻辑,将状态视为不可变,通过映射或过滤创建一个新的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 =&gt; if (s.id !== site.id) return s; return site; ); this.setState(sites); console.log(sites); 正确更新的站点列表被记录到控制台,但 React 不会重新渲染显示的更新列表。【参考方案2】:

一个简单的

componentWillReceiveProps()  

收到道具时触发,并将使用更新后的状态。

【讨论】:

以上是关于在 React 中更新后无法重新渲染的主要内容,如果未能解决你的问题,请参考以下文章

React Native:状态更改后无法重新渲染图像

react usestate 重新设置数据后,不渲染页面

在使用数据库数据更新上下文后,React 'useContext' 钩子不会重新渲染

React 状态在重新渲染后重置

即使 DB 已正确更新,React UI 也不会在单击时重新呈现。第二次点击后,UI 重新渲染

React Native:更新数据后未重新渲染组件