Skip to content

Conditional data fetching based on dynamic remote data #405

Closed
@taion

Description

@taion

This is a bit of a usage question (and might be on the wrong repo), but I think it might be interesting enough to warrant further discussion.

I'm looking to fetch data from my GraphQL server based on dynamic remote data.

For a simple example, imagine I'm rendering a list of todos, but the fields I want to render are different based on whether the todo in question is active or completed. Imagine a React component like:

function Todo({ todo }) {
  return (
    <div>
      {todo.text}
      {todo.status === 'completed' ?
        <CompletedTodoDetails todo={todo} /> :
        <ActiveTodoDetails todo={todo} />}
    </div>
  );
}

I can think of a couple of ways to define my GraphQL schema to allow this.

The most straightforward way is to have something like:

interface Todo { ... }

type ActiveTodo implements Todo { ... }
type CompletedTodo implements Todo { ... }

And then just define fragments on ActiveTodo or CompletedTodo as needed.

However, this is fairly limited – it's very awkward for defining conditionals on more than one field, requires the conditional to be like an enum, and is frankly confusing in the context of Relay, if I want to have this type be a node, but somehow have the concrete type of the node change under me.

Another option seems to be to do something like:

type Todo {
  self(status: String!): Todo
  ...
}

Then for the above example, I could write a fragment like

fragment on Todo {
  name
  self(status: "completed") {
    ${CompletedTodoDetails.getFragment('todo')}
  }
  self(status: "active") {
    ${ActiveTodoDetails.getFragment('todo')}
  }
}

This gives me a lot more flexibility over how to do the conditional. It still seems a bit awkward, though.

It seems like it'd be nice to do this with some sort of custom directive, but handling the custom directive myself seems to not admit a straightforward syntax, especially if I wanted to define that custom directive on a fragment.

Am I missing anything here?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions