parse-community/parse-react

Use in Next.js without getServerSideProps?

rshov opened this issue · 10 comments

rshov commented

Is it possible to use @parse/react-ssr without having to encode the query inside getServerSideProps?
I would like to have a static page that accesses parse from the front-end, but using getServerSideProps forces it to be server-side rendered.
Thanks!

In this case it might be easier you use the @parse/react package.

rshov commented

If I instead try using the @parse/react package in Next.js it throws an error:

import Parse from 'parse';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at wrapSafe (internal/modules/cjs/loader.js:979:16)
    at Module._compile (internal/modules/cjs/loader.js:1027:27)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14)
    at Module.require (internal/modules/cjs/loader.js:952:19)
    at require (internal/modules/cjs/helpers.js:88:18)

would you mind to share the code that you are using to initialize the lib?

rshov commented

Sure, this is the code for pages/dashboard.tsx. I'm trying to initialize parse only when running in the browser, not the server. But I get the same error whether I include the if statement or not.

import Parse from 'parse'
import { useParseQuery, initializeParse } from '@parse/react'

// Check if running in browser
if (typeof window !== 'undefined') {
  initializeParse(
    process.env.NEXT_PUBLIC_PARSE_SERVER_URL,
    process.env.NEXT_PUBLIC_PARSE_APP_ID,
    process.env.NEXT_PUBLIC_PARSE_JS_KEY
  )
}

const DashboardPage = () => {

  const parseQuery = new Parse.Query('Project')

  const {
    isLoading,
    results,
    error,
    reload
  } = useParseQuery(parseQuery)

  ...
}

I think the problem is actually this line import Parse from 'parse', right? Or does the error come from import { useParseQuery, initializeParse } from '@parse/react'?

rshov commented

I actually get the same error if I delete the line import Parse from 'parse'.

I think the error is coming from the `@parse/react' package, as that is the first line in that file: parse-react/packages/parse-react/src/index.ts

Maybe that conflicts with what webpack is expecting in Next.js? I don't know enough about webpack, but seems like that might be the problem.

This is the Next error shown in the browser:
image

And the console has this output:

error - C:\my-app-dir\node_modules\@parse\react\dist\index.js:1
import Parse from 'parse';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at wrapSafe (internal/modules/cjs/loader.js:979:16)
    at Module._compile (internal/modules/cjs/loader.js:1027:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14)
    at Module.require (internal/modules/cjs/loader.js:952:19)
    at require (internal/modules/cjs/helpers.js:88:18)
    at Object.@parse/react (C:\my-app-dir\.next\server\pages\dashboard.js:18193:18)
    at __webpack_require__ (C:\my-app-dir\.next\server\webpack-runtime.js:25:43)
    at Module../pages/dashboard.tsx (C:\my-app-dir\.next\server\pages\dashboard.js:2389:70) {
  page: '/dashboard'
}

The problem is happening because @parse/react is build with target esnext (which does not work in node.js). I will keep this issue open for us to think about a more convenient way to use the link on next.js without loading data on server. In the meantime, I'd try to do something like this:

import Parse from 'parse'
import { useParseQuery, initializeParse } from '@parse/react-ssr'

// Check if running in browser
if (typeof window !== 'undefined') {
  initializeParse(
    process.env.NEXT_PUBLIC_PARSE_SERVER_URL,
    process.env.NEXT_PUBLIC_PARSE_APP_ID,
    process.env.NEXT_PUBLIC_PARSE_JS_KEY
  )
}

const DashboardPage = () => {

  const parseQuery = new Parse.Query('Project')

  const {
    isLoading,
    results,
    error,
    reload
  } = typeof window !== 'undefined' ? useParseQuery(parseQuery) : {
    isLoading: true,
    results: undefined,
    error: undefined,
    reload: undefined

}

  ...
}
rshov commented

That makes sense. Unfortunately React doesn't like hooks to be called conditionally. Trying that, eslint complains with:

React Hook "useParseQuery" is called conditionally. React Hooks must be called in the exact same order in every component render. eslint(react-hooks/rules-of-hooks)

I believe that you can actually ignore this eslint check for this line, since on server it will never run, and on browser it will always run. Anyways, I've just merged an improvement regarding that. Now you can pass a parse query on server side (which will not be executed) but will not throw any error. Please try with the latest version and here it goes a usage example: https://github.com/parse-community/parse-react/blob/master/examples/next-ts-todo/pages/no-ssr.tsx

Let me know if that works.

rshov commented

Perfect, that works! Thanks @davimacedo
I appreciate your fast responses and fix on this.