【问题标题】:setState of specific object property within an array数组中特定对象属性的 setState
【发布时间】:2020-05-14 17:54:10
【问题描述】:

我希望该按钮在单击时将当前filteredTodo 的属性“过滤器”从真更改为假,但我在定位所述对象及其属性时遇到问题。

import React, {useState} from 'react';

const Todo = props => {

    const [todos, setTodos] = useState([]);
    const onSubmit = e =>{
        e.preventDefault();
        setTodos([
            ...todos, {
                name :e.target.name.value,
                filter :e.target.filter.value,
            }
        ])
        e.target.name.value = "";
        console.log(todos);
    }
    const onClick = e => {

    }
    return (
        <div>
            <div>
                <form onSubmit={onSubmit}>
                    <input type="text" placeholder="Get MERN black belt" name="name"/>
                    <input type="hidden" name="filter" value="true"/>
                    <button type="submit">Add</button>
                </form>
            </div>
            {todos.filter(todo=>todo.filter.includes("true")).map((filteredTodo,i) =>(
                <div key={i}>
                    <label>{filteredTodo.name}</label>
                    <input type="checkbox"/>
                    <button onClick={onClick} name="filter" type="submit">Delete</button>
                </div>
            ))}
        </div>
    );
}
export default Todo;

【问题讨论】:

    标签: reactjs setstate


    【解决方案1】:

    您可以简单地根据过滤条件映射并返回元素,而不是过滤和映射。这样你就可以依靠从 map 获得的 index 属性来更新点击时的 todo,因为你没有任何与 todos 关联的唯一 id

    const Todo = props => {
    
        const [todos, setTodos] = useState([]);
        const onSubmit = e =>{
            e.preventDefault();
            setTodos([
                ...todos, {
                    name :e.target.name.value,
                    filter :e.target.filter.value,
                }
            ])
            e.target.name.value = "";
            console.log(todos);
        }
        const onClick = index => {
           setTodos(prev => [...prev.slice(0, index), {...prev[index], filter: false}, ...prev.slice(index + 1)]);
        }
        return (
            <div>
                <div>
                    <form onSubmit={onSubmit}>
                        <input type="text" placeholder="Get MERN black belt" name="name"/>
                        <input type="hidden" name="filter" value="true"/>
                        <button type="submit">Add</button>
                    </form>
                </div>
                {todos.map((filteredTodo,index) =>{
                 if(odo.filter.includes("true")) {
                   return (<div key={i}>
                        <label>{filteredTodo.name}</label>
                        <input type="checkbox"/>
                        <button onClick={() => onClick(index)} name="filter" type="submit">Delete</button>
                    </div>
                   )
                 }
                 return null; // returning null will not render anything
                })}
            </div>
        );
    }
    export default Todo;
    

    但是,我建议您在创建待办事项时生成一个唯一的 id,以便您可以唯一地标识待办事项。它还将通过提供唯一 id 作为从地图返回的 div 元素的键来帮助您进行渲染优化

    【讨论】:

      【解决方案2】:

      解决了!感谢How do I update states onchange in an array of object in React Hooks

      import React, {useState} from 'react';
      
      const Todo = props => {
      
          const [todos, setTodos] = useState([]);
          const onSubmit = e =>{
              e.preventDefault();
              setTodos([
                  ...todos, {
                      name :e.target.name.value,
                      filter :e.target.filter.value,
                  }
              ])
              e.target.name.value = "";
              console.log(todos);
          }
          const onClick = i => e => {
              let newArr = [...todos];
              newArr[i].filter = "false";
              setTodos(newArr);
          }
          return (
              <div>
                  <div>
                      <form onSubmit={onSubmit}>
                          <input type="text" placeholder="Get MERN black belt" name="name"/>
                          <input type="hidden" name="filter" value="true"/>
                          <button type="submit">Add</button>
                      </form>
                  </div>
                  {todos.filter(todo=>todo.filter.includes("true")).map((filteredTodo,i) =>(
                      <div key={i}>
                          <label>{filteredTodo.name}</label>
                          <input type="checkbox"/>
                          <button onClick={onClick(i)} type="submit">Delete</button>
                      </div>
                  ))}
              </div>
          );
      }
      export default Todo;
      

      【讨论】:

      • 太好了,这只有在你的数组中的待办事项都将过滤状态设为真时才有效。如果中心的任何待办事项过滤状态为 false,这将失败
      • 您能详细说明一下吗?我设置了一个隐藏输入,因此每个待办事项都应设置为 true,一旦删除将设置为 false,但仍存储在数组中。我在这里错过了什么吗?
      • 如果你为一个待办事项设置了过滤为假,现在下次你尝试将过滤设置为假时,你将用你的代码更新一个错误的待办事项。你可以试试看。详情请查看我的回答
      猜你喜欢
      • 1970-01-01
      • 2019-08-22
      • 1970-01-01
      • 2022-01-01
      • 2020-12-05
      • 2015-11-05
      • 2018-10-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多