You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React新手删除按钮触发错误函数及setState写法规范咨询

React新增/删除列表功能故障及规范问题解答

一、原始故障代码的问题定位

你遇到的删除按钮触发新增逻辑的问题,一共存在3处错误:

  • 构造函数内方法绑定错误:this.elimFunction = this.clickFunction.bind(this)这行代码把删除方法错误绑定成了新增方法,自然点击删除会触发新增逻辑,需要改成this.elimFunction = this.elimFunction.bind(this)
  • 删除索引传参错误:调用删除方法时你传的是{i}(包裹了一层对象),不是数字类型的索引,需要改成this.elimFunction(i)
  • splice用法错误:Array.splice()的返回值是被删除的元素组成的数组,不是修改后的原数组,直接把返回值赋值给列表会导致列表只剩下被删除的条目,需要先拷贝原数组再操作。

二、可运行版本的规范问题说明

你担心的“setState写在render里”属于理解误区:你并没有在render的同步执行流程中调用setState,只是把setState写在了按钮的点击事件回调里,回调只会在你主动点击按钮时触发,不会在渲染阶段执行,因此不会触发无限重渲染的问题。

但这个写法仍然不符合最佳实践,存在两个问题:

  • 视图和业务逻辑耦合:所有新增、删除逻辑都堆在JSX的回调内,代码量变大后可读性、可维护性会非常差,也不利于逻辑复用
  • 直接修改原始state:删除逻辑中this.state.list.splice(i, 1)直接修改了state里的原数组,违反了React状态不可变的设计原则,可能引发潜在的渲染异常。

三、符合最佳实践的参考代码

<html>
  <head>
    <script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
    <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Faker/3.1.0/faker.min.js"></script>
  </head>
  <body>
    <div id='root'></div>
    <script type='text/babel'>
      const { render } = ReactDOM;
      const { Component } = React;

      class App extends Component{
        constructor(){
          super();
          this.state = {
            companyList: ['Some Company']
          }
          // 正确绑定两个方法的this指向
          this.addCompany = this.addCompany.bind(this)
          this.deleteCompany = this.deleteCompany.bind(this)
        }
        // 新增逻辑抽离为独立方法
        addCompany() {
          const newCompany = faker.company.companyName()
          this.setState({ 
            companyList: [...this.state.companyList, newCompany]
          })
        }

        // 删除逻辑抽离为独立方法,遵循不可变原则
        deleteCompany(index) {
          // 过滤得到新数组,不修改原state
          const newList = this.state.companyList.filter((_, i) => i !== index)
          this.setState({ companyList: newList })
        }
  
        render(){
          return (
            <div>
              <button onClick={this.addCompany}>  
                点击新增公司
              </button> 
              <ul> 
                {
                  this.state.companyList.map((e,i)=>
                    <li key={i}> 
                      {e} <button onClick={() => this.deleteCompany(i)}>删除</button>
                    </li> 
                  )
                }
              </ul> 
            </div>
          )
        }
      }

      render(<App />, document.querySelector('#root'));
    </script>
  </body>
</html>

内容的提问来源于stack exchange,提问作者Ken

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 11:27:06