jaydenseric / graphql-react

A GraphQL client for React using modern context and hooks APIs that is lightweight (< 4 kB) but powerful; the first Relay and Apollo alternative with server side rendering.
https://npm.im/graphql-react
MIT License
717 stars 22 forks source link

Usage with class components? #21

Closed chrischen closed 5 years ago

chrischen commented 5 years ago

There's an example in the docs showing the use of the Query component, but it no longer works. I'm assuming I use GraphQLContext.Consumer instead, but is there an example of usage with this? (I'm getting an infinite loop if I do graphql.operate() call in render()).

jaydenseric commented 5 years ago

There's an example in the docs showing the use of the Query component

Where? There should be none anymore, the Query component has been removed in the latest version.

React hooks can't be used in class components; I suggest refactoring your class to hooks.

You could create your own Query component using the useGraphQL hook if you like.

chrischen commented 5 years ago

This example linked in the components: https://github.com/zeit/next.js/blob/canary/examples/with-graphql-react/pages/index.js

jaydenseric commented 5 years ago

That example is for graphql-react v6: https://github.com/zeit/next.js/blob/canary/examples/with-graphql-react/package.json#L7

I am rolling out the new version in my projects, and once I have a bit more experience with the hooks I will PR Next.js to update the example.

jaydenseric commented 5 years ago

This example is using the latest version with hooks: https://graphql-react.now.sh

mike-marcacci commented 5 years ago

For what it's worth, it's quite trivial to turn a hook int a HOC for use alongside existing class components. This is probably a great migration strategy.

export default function Query({ query, children, ...other }) {
    return children(useGraphQL(other))
}
chrischen commented 5 years ago

Getting Invariant Violation: Hooks can only be called inside the body of a function component.

import * as React from "react";
import { useGraphQL } from 'graphql-react'

const Query = ({ query, children }: { query: string, children: any }) => {
  const { loading, cacheValue = {} } = useGraphQL({
    fetchOptionsOverride(options: any) {
      options.url = 'http://localhost:4000/graphql'
    },
    operation: {
      query
    }
  });

  return <>
    {children({ loading, cacheValue })}
  </>;
}
export default Query;

I'm testing it within the index.tsx class component

<Query query={ GET_MESSAGES }>
          { ({ loading, cacheValue }) => {
            console.log('data');
            console.log(cacheValue.data);
            return 'yes';
          }}
</Query>
mike-marcacci commented 5 years ago

Hmmm... I'm not sure what's going on there. I just double checked, and this technique works exactly as expected with useState at least:

https://codesandbox.io/s/7yl1lx27x6

import React, { useState } from "react";
import ReactDOM from "react-dom";

const Injector = ({children}) => {
  const [inputValue, setInputValue] = useState("default text");
  return (
    <div>
      {children(inputValue, (e) => setInputValue(e.target.value))}
    </div>
  );
}

const Main = () => {
  return <Injector>{(value, onChange) => <input value={value} onChange={onChange} />}</Injector>
}

const rootElement = document.getElementById("root");
ReactDOM.render(<Main />, rootElement);
chrischen commented 5 years ago

It's possible to use functional component inside of then render method of a class component right (that's what we're trying to solve after all)?

I looked around and the error was caused by a few other issues as well:

1) If multiple React instances are being used in a project. 2) Old version of react-hot-loader or react-dom

I've ruled both of those out and my react-dom is 16.8.2. Will have to test with useState and report back.

On Feb 19, 2019, at 2:25 AM, Mike Marcacci notifications@github.com wrote:

Hmmm... I'm not sure what's going on there. I just double checked, and this technique works exactly as expected with useState at least:

https://codesandbox.io/s/7yl1lx27x6 https://codesandbox.io/s/7yl1lx27x6 import React, { useState } from "react"; import ReactDOM from "react-dom";

const Inkjector = ({children}) => { const [inputValue, setInputValue] = useState("default text"); return (

{children(inputValue, (e) => setInputValue(e.target.value))}

); }

const Main = () => { return {(value, onChange) => } }

const rootElement = document.getElementById("root"); ReactDOM.render(

, rootElement); — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/jaydenseric/graphql-react/issues/21#issuecomment-464818641, or mute the thread https://github.com/notifications/unsubscribe-auth/AAGsPgcDxADNKX11V59L7242rH7xfu79ks5vOuHygaJpZM4bATFV.