Skip to content
This repository has been archived by the owner on Apr 13, 2023. It is now read-only.

3.0 has more restrictive JSX types than React allows for queries & mutations #3314

Closed
ghost opened this issue Aug 5, 2019 · 2 comments
Closed
Labels
bug-upstream Bug confirmed to originate from a dependency help-wanted

Comments

@ghost
Copy link

ghost commented Aug 5, 2019

Intended outcome:

The child renderers of mutation, query, and subscription components should accept valid react nodes (i.e. React.ReactNode as it accepted in the 2.x branch)

Actual outcome:

Types have been redefined to JSX.Element | null. This type is unnecessarily restrictive and prevents various patterns such as:

bool && <component>, arrays of children, etc. Suggest JSX.Element | null -> React.ReactNode as the child return types for all 3 ComponentOptions

How to reproduce the issue:

Version

  System:
    OS: macOS 10.14.6
  Binaries:
    Node: 10.16.0 - /usr/local/bin/node
    Yarn: 1.17.3 - ~/airlab/repos/nova/node_modules/.bin/yarn
    npm: 6.9.0 - /usr/local/bin/npm
  Browsers:
    Chrome: 76.0.3809.87
    Safari: 12.1.2
  npmPackages:
    apollo: ^2.16.3 => 2.16.3
    apollo-client: ^2.5.1 => 2.6.3
    react-apollo: ^3.0.0-beta.4 => 3.0.0-beta.4
@hwillson hwillson self-assigned this Aug 6, 2019
@hwillson
Copy link
Member

Thanks for reporting this @markkahn. This was changed to JSX.Element | null because the Query, Mutation and Subscription components were converted from being class based components to functional components. Functional components can't return ReactNode's. This is a long-standing issue, and is being tracked in:

Fixing this properly is dependent on microsoft/TypeScript#21699 being addressed by the TS team. A PR was submitted a while back to fix this upstream, but it has been sitting there: microsoft/TypeScript#29818

If you or anyone else has suggestions on how we can fix this now, we're definitely all ears (and would review a PR). To fix this we could consider switching back to ReactNode as you suggested, and then wrapping our internal props.children calls in a fragment like:

export function Mutation<TData = any, TVariables = OperationVariables>(
  props: MutationComponentOptions<TData, TVariables>
) {
  // ...
  return props.children ? <>props.children(runMutation, result)</> : null;
}

but that seems kinda horrible. Regardless, we're definitely open to suggestions. The only caveats are that we don't want to switch back to class based components, and whatever changes are proposed have to work with the graphql HOC as well (which wraps the Query, Mutation and Subscription components).

@hwillson hwillson removed their assignment Aug 27, 2019
@hwillson hwillson added bug-upstream Bug confirmed to originate from a dependency help-wanted labels Aug 27, 2019
@hwillson
Copy link
Member

hwillson commented Sep 6, 2019

I'll close this for now due to the reasons outlined in #3314 (comment), but will happily re-open if anyone has a better solution / workaround we can implement (or until #3314 (comment) is finalized).

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug-upstream Bug confirmed to originate from a dependency help-wanted
Projects
None yet
Development

No branches or pull requests

1 participant