如何在 React 中更改处于状态的数组元素

Posted

技术标签:

【中文标题】如何在 React 中更改处于状态的数组元素【英文标题】:How to change an array element in state in a React 【发布时间】:2020-01-27 23:24:08 【问题描述】:

我正在尝试使用 handleToggle 方法更改数组的元素,但出现错误,我做错了什么,为什么我总是要在 React 中返回一个新数组?

子组件:

    function Todolist(props) 
      const todoItem = props.todos.map((todo, index) =>
        <ListItem key=todo.id dense button>
          <ListItemIcon>
            <Checkbox checked=todo.completed onChange=props.onChange(todo.id) edge="start"/>
          </ListItemIcon>
          <ListItemText primary=todo.title />
          <ListItemSecondaryAction>
            <IconButton edge="end" aria-label="comments"></IconButton>
          </ListItemSecondaryAction>
        </ListItem>
      )
      return (
        <div>
          todoItem
        </div>
      )
    

父组件:

class App extends React.Component 
  constructor(props) 
    super(props);
    this.state = 
      value: '',
      todos: [
        
          title: 'Learn React',
          id: Math.random(),
          completed: true
        
      ]
    
  ;

  handleChange = (evt) => 
    this.setState(
      value: evt.target.value
    )
  ;

  handleSubmit = (evt) => 
    evt.preventDefault();

    const todos = [...this.state.todos];

    todos.push(
      title: this.state.value,
      id: Math.random(),
      completed: false
    );

    this.setState(state => (
      todos,
      value: ''
    ))
  ;

  handleToggle = (id) => 
    const todos = [...this.state.todos];

    todos.map(todo => 
      if (todo.id === id) 
        return todo.completed = !todo.completed
       else 
        return todo
      
    );

    this.setState(state => (
      todos
    ))
  ;

  render() 
    return (
      <div className="App">
        <Grid className="Header" justify="center" container>
          <Grid item xs=11>
            <h1 className="Title">My to-do react app</h1>
            <FormBox value=this.state.value onSubmit=this.handleSubmit onChange=this.handleChange/>
          </Grid>
        </Grid>
        <TodoList todos=this.state.todos onChange=this.handleToggle />
      </div>
    );
  

错误文本:

已超过最大更新深度。当组件在 componentWillUpdate 或 componentDidUpdate 中重复调用 setState 时,可能会发生这种情况。 React 限制了嵌套更新的数量以防止无限循环。

【问题讨论】:

【参考方案1】:

你正在立即执行onChange

onChange=props.onChange(todo.id)

将回调包装在arrow function

onChange=() => props.onChange(todo.id)

您的 handleToggle 也没有正确更改值(变异),请尝试这样

handleToggle = (id) => 
    const todos = [...this.state.todos];

    this.setState( todos : todos.map(todo => (
         ...todo, 
         completed : todo.id === id ? !todo.completed : todo.completed
     ) ))
  

【讨论】:

map 返回一个新数组,因此他还应该在将结果设置为 state 之前将结果收集到数组中。 嘿伙计,我想他只想将具有指定 id 的待办事项更改为已完成 错误是因为我忘记将返回的对象包装在( )中。是的(也错过了),我正在更新答案 谢谢,我的错误是在箭头函数的回调中 不客气!!您正在通过执行todo.completed = !todo.completed 来改变状态,请尝试改用spread 运算符。但是你的代码没有错。只是反模式

以上是关于如何在 React 中更改处于状态的数组元素的主要内容,如果未能解决你的问题,请参考以下文章

如何更改数组状态容器中的对象属性? React Hooks 使用状态

如何在 React js 中创建状态数组

React:全局状态属性的异步更改

如何检查Mysql中是不是存在数组元素?

如何在 React 中使用带有钩子的 onChange 更新数组元素?

如何更新 React 组件的数组?