12

I'm following a graphql tutorial on youtube (https://www.youtube.com/watch?v=ed8SzALpx1Q at about 3hr 16min) and part of it uses compose from "react-apollo". However, I'm getting an error because the new version of react-apollo does not export this.

I read online that I need to replace import { compose } from "react-apollo" with import { compose } from "recompose" but doing that produces the error TypeError: Cannot read property 'loading' of undefined I've also read that I should replace the import from react-apollo with import * as compose from "lodash" but when I do this I get other errors, saying that × TypeError: lodash__WEBPACK_IMPORTED_MODULE_2__(...) is not a function

App.js:

import React from "react";
import ApolloClient from "apollo-boost";
import { ApolloProvider } from "react-apollo";

import BookList from "./components/BookList";
import AddBook from "./components/AddBook";

//apollo client setup
const client = new ApolloClient({
  uri: "http://localhost:4000/graphql"
});

function App() {
  return (
    <ApolloProvider client={client}>
      <div className="main">
        <h1>My Reading List</h1>
        <BookList />
        <AddBook />
      </div>
    </ApolloProvider>
  );
}

export default App;

queries.js:

import { gql } from "apollo-boost";

const getBooksQuery = gql`
  {
    books {
      name
      id
    }
  }
`;

const getAuthorsQuery = gql`
  {
    authors {
      name
      id
    }
  }
`;

const addBookMutation = gql`
  mutation {
    addBook(name: "", genre: "", authorId: "") {
      name
      id
    }
  }
`;

export { getAuthorsQuery, getBooksQuery, addBookMutation };

AddBooks.js:

import React, { Component } from "react";
import { graphql } from "react-apollo";
import { compose } from "recompose";
// import * as compose from "lodash";
import { getAuthorsQuery, addBookMutation } from "../queries/queries";

class AddBook extends Component {
  state = {
    name: "",
    genre: "",
    authorId: ""
  };

  displayAuthors = () => {
    let data = this.props.data;
    if (data.loading) {
      return <option>loading authors...</option>;
    } else {
      return data.authors.map(author => {
        return (
          <option key={author.id} value={author.id}>
            {author.name}
          </option>
        );
      });
    }
  };

  submitForm(e) {
    e.preventDefault();
    console.log(this.state);
  }

  render() {
    return (
      <form onSubmit={this.submitForm.bind(this)}>
        <div className="field">
          <label>Book name: </label>
          <input
            type="text"
            onChange={e => {
              this.setState({ name: e.target.value });
            }}
          />
        </div>
        <div className="field">
          <label>Genre: </label>
          <input
            type="text"
            onChange={e => {
              this.setState({ genre: e.target.value });
            }}
          />
        </div>
        <div className="field">
          <label>Author: </label>
          <select
            onChange={e => {
              this.setState({ authorId: e.target.value });
            }}
          >
            <option>Select author</option>
            {this.displayAuthors()}
          </select>
        </div>
        <button>+</button>
      </form>
    );
  }
}

export default compose(
  graphql(getAuthorsQuery, { name: "getAuthorsQuery" }),
  graphql(addBookMutation, { name: "addBookMutation" })
)(AddBook);

I expected compose to be imported from react-apollo and to take the query and mutation and make them available inside of AddBook's props, so I can use them in the displayAuthors() and submitForm() funtions, but instead I get the error that it is not exported from react-apollo, and when I try the suggested solutions I found online I get the other errors mentioned above.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
rollerpigeon
  • 209
  • 2
  • 5
  • 14

10 Answers10

20

compose was removed from React Apollo 3.0.0. If you want to use the same HOC pattern, feel free to use the same copy of lodash's flowRight.

Install lodash in your client folder

npm install lodash 

and use this to import compose from lodash (use a capital R in flowRight)

import {flowRight as compose} from 'lodash';

Reference for the braking changes

Anand Raja
  • 2,676
  • 1
  • 30
  • 35
Stéphane Gerber
  • 1,388
  • 1
  • 17
  • 30
  • Do you have a vanilla solution? – Kevin Aug 15 '19 at 11:38
  • 2
    I'd like to know why `composer` was removed, before start using a hack solution. if compose was removed is because is a bad practice or something, so what is the better approach. – Victor Santos Aug 17 '19 at 19:23
  • 1
    compose has been removed https://github.com/apollographql/react-apollo/blob/e9190fac891dd7af3a1690a5d2a1305953fd5a6f/Changelog.md#breaking-changes, it was just a copy of lodash's flowRight https://github.com/apollographql/react-apollo/issues/3330 – Stéphane Gerber Aug 18 '19 at 11:05
6

compose was removed from React Apollo 3 (see the Breaking Changes). Now, to use compose, use lodash's flowRight.

Install flowright:

yarn add lodash.flowright

Replace in your code:

import { compose } from 'react-apollo'

by

import {flowRight as compose} from 'lodash';

Alan
  • 9,167
  • 4
  • 52
  • 70
2

Below is how I solved this issue with my project:

  1. install lodash.flowright

    npm install lodash.flowright

  2. import it in your AddBook.js or in the file that you want to use compose

    import compose from 'lodash.flowright'

DiaMaBo
  • 1,879
  • 1
  • 18
  • 18
2

This can be solved by ;

npm install lodash.flowright
import * as compose from 'lodash.flowright';

Because compose is literally the same as flowRight, the apollo team decided to reduce the bundle size by removing it.

For more info read the breaking changes section here https://github.com/apollographql/react-apollo/blob/e9190fac891dd7af3a1690a5d2a1305953fd5a6f/Changelog.md#breaking-changes

Roninho
  • 336
  • 2
  • 7
2

The problem is not with compose. whenever we compose 2 or more queries we don't get "data" property you should try

let data = this.props.getAuthorsQuery;

0

same here I try to follow his tutorial "https://www.youtube.com/watch?v=rHw0_A4SJxo&list=PL4cUxeGkcC9iK6Qhn-QLcXCXPQUov1U7f&index=31", and stuck at the compose site here is how I fix it: - install lodash : npm lodash - import flowRight :

import React, { Component } from 'react';
//import { compose } from "recompose";
import {flowRight as compose} from 'lodash';
import {graphql} from 'react-apollo';
import {getAuthorsQuery,addBookMutation} from '../queries/queries';
0
import React, {Component} from 'react';
import {getAuthersQuery , AddBookMutation } from '../quearies/quearies'

import { gql } from 'apollo-boost'            

import { graphql } from 'react-apollo'        
import {flowRight as compose} from 'lodash';   
Roberto Caboni
  • 7,252
  • 10
  • 25
  • 39
  • 2
    Please don't post only code as answer, but also provide an explanation what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes. – Mark Rotteveel Jul 18 '20 at 10:12
0

This Is how I got it working without using Compose.

I used useQuery to Query the authors and then used graphql to Mutate. Simply avoiding to nest Queries, which required using compose.

Its just a way to get around Compose (avoiding) and get the tutorials going, time is of great essence

import {useQuery} from "@apollo/react-hooks";
import React, {useState} from "react";
import {getAuthorsQuery, addBookMutation} from "../queries/queries.js";
import { graphql } from "react-apollo";
// import { flowRight as compose } from "lodash";
// import {* as compose} from "lodash.flowRight";


const AddBook = (props) => {
const [formData, setFormData] = useState({
    name : "",
    genre : "",
    authorId : ""
});

const authorsData = useQuery(getAuthorsQuery);


function displayAuthors(){

    console.log(authorsData)

    if(authorsData.loading){
        return( <option disabled >Loading Authors...</option> )
    }
    else{
        return( authorsData.data.authors.map(author => {
            return( <option key={author.id} value={author.id}>{author.name}</option>)
        }))
    }
}

function submitForm(e){
    e.preventDefault();
    console.log(formData);
}
    
return(
        <form id="add-book" onSubmit={(e) => submitForm(e)}>
            <div className="field" >  
                <label>Book Name:</label>
                <input type="text" onChange={(e) => setFormData({name : 
e.target.value})}/>
            </div>

            <div className="field" >  
                <label>Genre:</label>
                <input type="text" onChange={(e) => setFormData({genre : 
e.target.value})}/>
            </div>

            <div className="field" >  
                <label>Author:</label>
                <select onChange={(e) => setFormData({authorId : e.target.value})}>
                    <option>Select Author</option>
                    {displayAuthors()}
                </select>
            </div>

        <button>+</button>
    </form>
)}
export default graphql(addBookMutation)(AddBook);

I hope this help you finish up you graphql tutorials, but if you are looking into solving compose issues? Well I'm also struggling with that.

Gesy Darati
  • 113
  • 1
  • 6
0

wow i am also doing the same project from the net ninja youtube tutorial and got the same error actually the version of react-oppollo is changed with the passage of time

-2

You don't have to use lodash at least for this problem

Simply nest graphql function

export default graphql(addBookMutation)(graphql(getAuthorsQuery)(AddBook))

You can refer this

Apollo concepts