Search code examples
javascriptgraphqlapolloapollo-client

Apollo Client - useQuery - how to set parameter as optional


I have this query:

const CURRENT_MONTH_BY_USER = gql`
  query getCurrentMonthByUser($selectedMonth: String!, $username: String) {
    getCurrentMonthByUser(selectedMonth: $selectedMonth, username: $username) {
      id
      itemDate
      itemName
      itemCategory
      itemPrice {
        price
        currency
      }
      itemUpdated {
        isUpdated
        updatedBy
        updateStamp
      }
      createdBy {
        username
        name
        date
      }
    }
  }
`

Snippet from component:

  const result = useQuery(CURRENT_MONTH_BY_USER, {
    variables: { selectedMonth, username },
  })

On backend, graphQL query the code is as follows:

    getCurrentMonthByUser: async (_, args) => {
      try {
        const allItems = await Item.find({})

        const items = allItems
          .filter(item => item.itemDate.substring(0, 7) === args.selectedMonth)
          .filter(item => item.createdBy.username === args.username)

        return items
      } catch (err) {
        throw new Error('Specific month not found')
      }
    }

typeDef:

  type Query {
    getCurrentMonthByUser(selectedMonth: String!, username: String): [Item]
  }

My question is, if username is not supplied, the query does not work, returns nothing, how to make the username optional? I didn't set it in the query as required.

My current workaround is to use the Query resolver accordingly, however it's not really ideal in case there'd be more optional parameters

    getCurrentMonthByUser: async (_, args) => {
      try {
        const allItems = await Item.find({})
        let items = []
        if (args.username) {
          items = allItems
            .filter(item => item.itemDate.substring(0, 7) === args.selectedMonth,)
            .filter(item => item.createdBy.username === args.username)
          return items
        }

        items = allItems.filter(
          item => item.itemDate.substring(0, 7) === args.selectedMonth,
        )
        return items
      } catch (err) {
        throw new Error('Specific month not found')
      }
    },

Thank you.


Solution

  • username is optional in your schema definition. The reason you don't get anything back is because the username is undefined when not provided; so the filter can't find anything to return.

    This should work:

        getCurrentMonthByUser: async (_, args) => {
          try {
            const allItems = await Item.find({})
    
            const items = allItems
              .filter(item => item.itemDate.substring(0, 7) === args.selectedMonth)
              .filter(item => args.username ? item.createdBy.username === args.username : true)
    
            return items
          } catch (err) {
            throw new Error('Specific month not found')
          }
        }