开发者问题收集

如何更新数组内对象的内容 javascript

2020-07-10
85

我的对象数组中有一个 booksOwned ,我想将另一本书添加到 “John Doe” 的 booksOwned 中。

const [ownerInfo, setOwnerInfo] = React.useState([
  {
    owner: "John Doe",
    booksOwned: ["To Kill a Mockingbird", "1984"],
  },
  {
    owner: "John Doe Jr",
    booksOwned: [
      "Harry Potter and the Philosopher's Stone",
      "The Lord of the Rings",
    ],
  },
])

这是我目前尝试过的方法,似乎不起作用。

let data = ownerInfo
let newBook = "Pride and Prejudice"

//to store currently owned books
let currBooks = []

//get the index of object I need
let ind = data.map((val, i) => {
  if (val.owner === "John Doe") {
    currBooks = val.booksOwned
    return i
  } else {
    return -1
  }
})

let bookIndex = currBooks.indexOf(newBook)

//insert only if book does not yet exist
if (bookIndex === -1) {
  data[ind] = {
    owner: "John Doe",
    booksOwned: currBooks.push(newBook),
  }
  setOwnerInfo(data)
}
2个回答

一种简单的方法是使用函数式 setState。基本上,setState 可以接受函数作为其参数。类似这样的内容:

const newBook = 'Pride and Prejudice'

// When using setOwnerInfo with functions as argument, it
// receives currentState as argument so we can use it.

// Use map to create a new array, instead of modifying it.
setOwnerInfo(owners => owners.map(owner => {
  // First check for correct owner. Return if this is wrong one.
  if (owner.onwer !== "John Doe") { return owner }

  // Second, check that book doesn't exist already. Return if it does.
  if (owner.booksOwned.find(ownedBook => ownedBook === newBook) !== undefined) { return owner }

  // Book doesn't exist. Add it.
  // Let's create a new object, instead of mutating it.
  return {...owner, booksOwned: [...owner.booksOwner, newBook]}
}))

关于 React 状态的一件事是,您不应该对其进行变异。这可能会导致许多错误。最好只是复制它,以免将来麻烦。

如果您想过滤掉一本书,您可以像这样更改它:

setOwnerInfo(owners => owners.map(owner => {
  // First check for correct owner. Return if this is wrong one.
  if (owner.onwer !== "John Doe") { return owner }

  // Filter here
  // Let's create a new object, instead of mutating it.
  return {...owner, booksOwned: owner.booksOwned.filter(ownedBook => ownedBook !== newBook)}
}))

这应该会删除与 newBook 匹配的所有数组项(即使以某种方式存在重复项,这不应该发生,因为我们上面正在防止重复项)。

Reel
2020-07-10

这是在 ES6 Javascript 中执行此操作的简单方法:

// owner set to name of the owner
// newBook set to book title
const addBook = (owner, newBook) => {
  // Find owner by name
  const person = ownerInfo.find(person => person.owner === owner)
  // if book already owned escape function
  person.booksOwned.find(exists => { if(exists == newBook) return })
  // Add book to owned books
  person.booksOwned.push(newBook)
}

// example on how to use
addBook("John Doe", "New Book")

或者,如果您想将其与 setState 一起使用:

const addBook = (owner, newBook) => {
  const person = ownerInfo.find(person => person.owner === owner)
  const newOwnerInfo = person.booksOwned.push(newBook)
  person.booksOwned.find(exists => { if(exists == newBook) return })
  setOwnerInfo(newOwnerInfo) // to change state
}

此功能可用于任何所有者。

希望这对您有所帮助。

Fletcher Rippon
2020-07-10