为了账号安全,请及时绑定邮箱和手机立即绑定

React Hooks,useState 相关问题。如何更新对象的一个​​属性并保留其余的

React Hooks,useState 相关问题。如何更新对象的一个​​属性并保留其余的

慕森王 2023-04-27 16:56:26
我想用挂钩做一个待办事项列表。这是我的相关代码。function generateId() {  return '_' + Math.random().toString(36).substr(2, 9);};export function TodoList(){  const [todos, setTodos] = React.useState([])  const [input, setInput] = React.useState('')  const [time, setTime] = React.useState('')  const handleSubmit = () => {    setTodos((todos) => todos.concat({      text: input,      id: generateId(),      timeRequired: time,    }))    setInput('')    setTime('')  }  // remove to do works fine.  const removeTodo = (id) => setTodos((todos) => todos.filter((todo) => todo.id !== id ))  /// confusion here   let todo = (id) => todos.find(x => x.id = id)  const decrement = (id) => setTodos((todo(id).timeRequired) => timeRequired - 1)   ///   return(    <React.Fragment>      <input type="text" value={input} placeholder="New Task" onChange={(e) => setInput(e.target.value)}>       </input>      <input type="number" value={time} placeholder="Hours Required" onChange={(e) => setTime(e.target.value)}>      </input>      <button onClick={handleSubmit}> Submit </button>      <ul>        {todos.map(({text, id, timeRequired}) => (          <li key={id}>            <span>{text}: remaining {timeRequired} hours </span>             <button onClick={() => removeTodo(id)}>               Cancel ❌             </button>            <button onClick={() => decrement(id)}> Decrement ➖ </button>             <button > Increase ➕ </button>             <button> Done ✔️ </button>          </li>        ))}      </ul>    </React.Fragment>  )}所以我想增加/减少待办事项列表上的剩余时间。但是,我不知道如何选择列表中的特定项目并更改一个属性(剩余时间)并保留文本属性。
查看完整描述

4 回答

?
翻阅古今

TA贡献1780条经验 获得超5个赞

下面是该decrement函数的外观。这需要id, 循环遍历所有todos. 如果 atodo与提供的不匹配,id请保持原样。如果确实匹配,则创建对象的浅表副本 ( ) 并使用更新后的值{...todo}覆盖该属性。timeRequired


const decrement = (id) => setTodos((todos) => todos.map((todo) => {

  if (todo.id != id) return todo;

  return {...todo, timeRequired: todo.timeRequired - 1};

}));

请注意,顺序{...todo, timeRequired: todo.timeRequired - 1}很重要。通过放置在它将覆盖现有属性timeRequired: todo.timeRequired - 1之后。...todo就像 object{a: 1, b: 2, a: 3}会把 object 留给你一样{a: 3, b: 2},因为 key 的第二个定义a覆盖了第一个。


查看完整回答
反对 回复 2023-04-27
?
至尊宝的传说

TA贡献1789条经验 获得超10个赞

你可以这样试试



  const decrement = (id) => {

    

    const targetTodo = todos.find(x => x.id == id);  //get the todo


    const currentTime = targetTodo.timeRequired -1 //decrease the time 

    

    const newTodo = { ...targetTodo , timeRequired : currentTime } // create new todo object

    

    const newTodoList = todos.map( item => { // finally replace the old todo object

        if(item.id = id)  return newTodo

        else return item;

    })

    

    setTodos(newTodoList) 


  }


查看完整回答
反对 回复 2023-04-27
?
慕尼黑5688855

TA贡献1848条经验 获得超2个赞

识别数组中的元素后,从 todo 创建一个具有递减timeRequired属性的新对象。然后使用.slice在新项前后对数组进行切片,新项在中间:


const decrement = (i) => {

    const replacedTodo = {

        ...todos[i],

        timeRequired: todos[i].timeRequired - 1,

    };

    setTodos(

        todos.slice(0, i),

        replacedTodo,

        todos.slice(i + 1),

    );

};

{todos.map(({ text, id, timeRequired }, i) => (

  // ...

  <button onClick={() => decrement(i)}> Decrement ➖ </button>

.map直接使用函数中的索引比稍后从 ID 中查找匹配元素更容易。


查看完整回答
反对 回复 2023-04-27
?
一只甜甜圈

TA贡献1836条经验 获得超5个赞

尝试这个...


const removeTodo = (id) => setTodos((todos) => todos.filter((todo) => todo.id !== id ))

const decrement = (id) => setTodos((todos) => todos.map((todo) => {

  const {

    id: oldID,

    timeRequired,

  } = todo;

  return {

    ...todo,

    timeRequired: id===oldID? timeRequired-1 : timeRequired, 

  };

}));


查看完整回答
反对 回复 2023-04-27
  • 4 回答
  • 0 关注
  • 242 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信