0
votes

I've been trying to run a MERN stack app on Heroku in which I am using both Express and GraphQL. Express for authentication and updates. GraphQL for fetching data for login options (which school you want to sign in to) & save data to React.Context upon login that is related to the user.

I finished the proposed part of the project and deployed the app to Heroku for testing and gathering feedback.

  • The app builds successfully
  • Environment variables for mongodb_uri is provided

The problem is when I open the app, the front disappears after a few seconds when the server responds that the GraphQL connection is refused. However, the app running on my pc running perfectly fine with nodemon using concurrently.

I am totally hopeless since:

  • The app using CORS
  • graphiql is false

Procfile contains the proper path to the server app and on the front proxy included to connect to 8080 as the app running on 3000.

Heres related code example for the front:

// index.js
const client = new ApolloClient({
  uri: 'http://localhost:8080/graphql'
})

ReactDOM.render(
  <React.StrictMode>
    <ApolloProvider client={client} >
      <Router>
        <App />
      </Router>
    </ApolloProvider>
  </React.StrictMode>,
  document.getElementById('app')
);

And the back:

// connect to DB
mongoose.connect(process.env.MONGODB_URI || 'mongodb://localhost/unimeetingsapp', {
    useNewUrlParser: true,
    useUnifiedTopology: true,
    useFindAndModify: false,
    useCreateIndex: true
});
mongoose.connection.on('open', ()=>{
    console.log('Connected to Database')
});

// heroku
if (process.env.NODE_ENV === "production") {
    app.use(express.static("../client/build"));
}
  
app.use(bodyParser.json());
app.use(cors());
//app.use(express.urlencoded({ extended: false }));

//////////////////////
// Routes
//////////////////////

// user Auth
app.use("/api", userAuth);
// user Events
app.use("/userevent", addEvent);
app.use("/userevent", confirmEvent);
app.use("/userevent", notification);
// org Auth
app.use("/api/org", orgAuth);
// org Events
app.use("/api/org", register);

app.use('/graphql', graphqlHTTP({
    schema: schema,
    graphiql: false
}))

I have not a clue anymore as if I enable graphiql I can access it just by putting url+/graphql so the ports are probably not the problem, and if I miss something in Procfiles Heroku would throw an error log.

I think the server gets the request for the options to load before it would fire up so it just refuses to connect. Any hint on how to solve that if that could be the problem?

I request the data with graphql from react-apollo in functional component and this is how I print on the front (coming from props):

        var data = schoolsData;
        if(data.loading) {
            return (<option > Loading Options ...</option>)
        } else {
            return data && data.schools.map(school => {
                return(
                <option key={school.id} value={school.id}>{school.name}</option>
                )
            })
        }
        
    } 

enter image description here 1: enter image description here

1
Add falisafe condition before doing it, data && data.schools && data.schools.map and handle the condition where you are missing the schools - kgangadhar
Thanks, now the page stays still, but GraphQL refuses the connection the same way :( - Krisztian Nagy

1 Answers

0
votes

Add this and let me know its working fine:

if (data.loading) {
  return (<option > Loading Options ...</option>)
} else {
  if (data && data.schools) {
    data.schools.map(school => {
      return (
        <option key={school.id} value={school.id}>{school.name}</option>
      )
    })
  }else{
    return (<option > Data issue, School is missing! </option>)
  }
}

you said connection refused after deployment it's because you are using localhost:8080 as server URL, try to replace it with the deployed server URL.

// index.js
const client = new ApolloClient({
  uri: '<server URL>/graphql' // Need to replace <server URL> with server URL
})

ReactDOM.render(
  <React.StrictMode>
    <ApolloProvider client={client} >
      <Router>
        <App />
      </Router>
    </ApolloProvider>
  </React.StrictMode>,
  document.getElementById('app')
);