Как написать распознаватель мутаций, чтобы изменить одно или несколько указанных c значений объекта? - PullRequest
1 голос
/ 19 февраля 2020

Представляется разумным ожидать, что один распознаватель будет обрабатывать ввод для любой комбинации одного или нескольких значений объекта. Мне не нужно было бы писать отдельные средства распознавания для «заголовка», «опубликованного», «автора» и т. Д. c., Верно?

Вот мой пример объекта:

let books = [
  {
    title: 'Clean Code',
    published: 2008,
    author: 'Robert Martin',
    id: 'afa5b6f4-344d-11e9-a414-719c6709cf8e',
    genres: ['refactoring'],
  },
  {
    title: 'Agile software development',
    published: 2002,
    author: 'Robert Martin',
    id: 'afa5b6f5-344d-11e9-a414-719c6709cf9e',
    genres: ['agile', 'patterns', 'design'],
  },
]

typeDefs:

const typeDefs = gql`
  type Book {
    title: String
    published: Int
    author: String
    id: ID
    genres: [String]
  }

  type Query {
    bookCount: Int!
    allBooks(title: String, author: String, genre: String): [Book]
    findBooks(title: String!): Book
  }

  type Mutation {
    addBook(
      title: String!
      published: Int
      author: String!
      genres: [String]
    ): Book
    editBook(
      id: ID
      title: String
      published: Int
      author: String
      genres: [String]
    ): Book
  }
`

Вот преобразователь, который у меня сейчас есть:

 Mutation: {
     editBook: (_, args) => {
      const book = books.find(b => b.id === args.id)
      if (!book) {
        return null
      }
      const updatedBook = {
        ...book,
        title: args.title,
        author: args.author,
        published: args.published,
        genres: [args.genres],
      }
      books = books.map(b => (
        b.id === args.id ? updatedBook : b))
      return updatedBook
    },
    }

Вот что В настоящее время происходит.

Исходный объект:

"allBooks": [
      {
        "id": "afa5b6f4-344d-11e9-a414-719c6709cf8e",
        "title": "Clean Code",
        "author": "Robert Martin",
        "published": 2008,
        "genres": [
          "refactoring"
        ]
      },
{...}
]

Запрос мутации:

mutation {
  editBook(id:"afa5b6f4-344d-11e9-a414-719c6709cf8e", title:"changed"){
    id
    title
    author
    published
    genres
  }
}

Возвращает это:

{
  "data": {
    "editBook": {
      "id": "afa5b6f4-344d-11e9-a414-719c6709cf8e",
      "title": "changed",
      "author": null,
      "published": null,
      "genres": [
        null
      ]
    }
  }
}

Как мне написать распознаватель, чтобы изменить одно или несколько значений объекта, не изменяя неопределенные значения на «ноль»?

Мои javascript навыки, я признаю, довольно шатки, и я предполагаю, что ответ ложь с более красноречивой функцией отображения, но поскольку код выполняется внутри модуля схемы graphql, он не обрабатывает console.log, поэтому устранение неполадок проблематично c. Любые рекомендации по этому вопросу также были бы чрезвычайно полезны, чтобы я мог лучше устранять свои собственные проблемы.

1 Ответ

0 голосов
/ 20 февраля 2020

Пара точек

Нет необходимости использовать карту или переназначать books. Поскольку переменная book является ссылкой на объект в массиве книг, вы можете изменить его (но не переназначить) и изменить объект в массиве. См. этот вопрос для получения дополнительной информации.

const book = books.find(b => b.id === args.id)
if (book) {
  // you cannot reassign book and still have the original value change,
  // but you can mutate it
  book.title = args.title
  book.author = args.author
  book.published = args.published
  book.genres = args.genres
}
return book

Чтобы изменить только значения, представленные в аргументах, у вас есть несколько вариантов:

Вы можете использовать логический оператор ИЛИ ( ||) чтобы указать другое значение, если первое значение равно false. Здесь book.title будет использоваться, только если args.title равно undefined, null, 0, NaN, "" или false.

book.title = args.title || book.title

. Вы можете используйте Object.assign , который копирует свойства из одного объекта в другой. Поскольку в args будут отсутствовать те свойства, которые не предоставлены, вы можете просто сделать что-то вроде приведенного ниже фрагмента. Это гораздо более элегантно и кратко, но будет работать только в том случае, если имена ваших аргументов совпадают с именами ваших свойств.

Object.assign(book, args)

Вы можете l oop через объект args. Это может быть более желательно, если у вас есть один или несколько аргументов, которые не соответствуют свойствам book:

Object.keys(args).forEach(argName => {
  const argValue = args[argName]
  book[argName] = argValue
})

Собрав все это вместе, мы могли бы сделать:

const book = books.find(b => b.id === args.id)
if (book) {
  Object.assign(book, args)
}
return book
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...