猿问

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

我想用挂钩做一个待办事项列表。这是我的相关代码。


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>

  )

}

所以我想增加/减少待办事项列表上的剩余时间。但是,我不知道如何选择列表中的特定项目并更改一个属性(剩余时间)并保留文本属性。


慕森王
浏览 254回答 4
4回答

翻阅古今

下面是该decrement函数的外观。这需要id, 循环遍历所有todos. 如果 atodo与提供的不匹配,id请保持原样。如果确实匹配,则创建对象的浅表副本 ( ) 并使用更新后的值{...todo}覆盖该属性。timeRequiredconst decrement = (id) => setTodos((todos) => todos.map((todo) => {&nbsp; if (todo.id != id) return todo;&nbsp; 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覆盖了第一个。

至尊宝的传说

你可以这样试试&nbsp; const decrement = (id) => {&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; const targetTodo = todos.find(x => x.id == id);&nbsp; //get the todo&nbsp; &nbsp; const currentTime = targetTodo.timeRequired -1 //decrease the time&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; const newTodo = { ...targetTodo , timeRequired : currentTime } // create new todo object&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; const newTodoList = todos.map( item => { // finally replace the old todo object&nbsp; &nbsp; &nbsp; &nbsp; if(item.id = id)&nbsp; return newTodo&nbsp; &nbsp; &nbsp; &nbsp; else return item;&nbsp; &nbsp; })&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; setTodos(newTodoList)&nbsp;&nbsp; }

慕尼黑5688855

识别数组中的元素后,从 todo 创建一个具有递减timeRequired属性的新对象。然后使用.slice在新项前后对数组进行切片,新项在中间:const decrement = (i) => {&nbsp; &nbsp; const replacedTodo = {&nbsp; &nbsp; &nbsp; &nbsp; ...todos[i],&nbsp; &nbsp; &nbsp; &nbsp; timeRequired: todos[i].timeRequired - 1,&nbsp; &nbsp; };&nbsp; &nbsp; setTodos(&nbsp; &nbsp; &nbsp; &nbsp; todos.slice(0, i),&nbsp; &nbsp; &nbsp; &nbsp; replacedTodo,&nbsp; &nbsp; &nbsp; &nbsp; todos.slice(i + 1),&nbsp; &nbsp; );};{todos.map(({ text, id, timeRequired }, i) => (&nbsp; // ...&nbsp; <button onClick={() => decrement(i)}> Decrement ➖ </button>.map直接使用函数中的索引比稍后从 ID 中查找匹配元素更容易。

一只甜甜圈

尝试这个...const removeTodo = (id) => setTodos((todos) => todos.filter((todo) => todo.id !== id ))const decrement = (id) => setTodos((todos) => todos.map((todo) => {&nbsp; const {&nbsp; &nbsp; id: oldID,&nbsp; &nbsp; timeRequired,&nbsp; } = todo;&nbsp; return {&nbsp; &nbsp; ...todo,&nbsp; &nbsp; timeRequired: id===oldID? timeRequired-1 : timeRequired,&nbsp;&nbsp; };}));
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答