NativeBase icon indicating copy to clipboard operation
NativeBase copied to clipboard

Support for Nextjs 12.2 and React 18.2

Open EuanGwd-AndDigital opened this issue 2 years ago • 9 comments

Description

Not really a bug, having issues adding Native base to an existing nextjs 12.2 app, the cli, examples and documentation seem to only refer to next 12.0 and react 17

CodeSandbox/Snack link

NA

Steps to reproduce

  1. install new create-next-app with typescript using yarn
  2. follow instructions in documentation on adding to existing project
  3. run yarn dev
  4. See error below

NativeBase Version

latest

Platform

  • [ ] Android
  • [ ] CRA
  • [ ] Expo
  • [ ] iOS
  • [X] Next

Other Platform

No response

Additional Information

Wondering if React18 is supported in nativebase as yet,

error:

warn  - Invalid next.config.js options detected:
[
  {
    "instancePath": "",
    "schemaPath": "#/additionalProperties",
    "keyword": "additionalProperties",
    "params": {
      "additionalProperty": "webpackDevMiddleware"
    },
    "message": "must NOT have additional properties"
  },
  {
    "instancePath": "",
    "schemaPath": "#/additionalProperties",
    "keyword": "additionalProperties",
    "params": {
      "additionalProperty": "configOrigin"
    },
    "message": "must NOT have additional properties"
  },
  {
    "instancePath": "",
    "schemaPath": "#/additionalProperties",
    "keyword": "additionalProperties",
    "params": {
      "additionalProperty": "target"
    },
    "message": "must NOT have additional properties"
  },
  {
    "instancePath": "",
    "schemaPath": "#/additionalProperties",
    "keyword": "additionalProperties",
    "params": {
      "additionalProperty": "analyticsId"
    },
    "message": "must NOT have additional properties"
  },
  {
    "instancePath": "",
    "schemaPath": "#/additionalProperties",
    "keyword": "additionalProperties",
    "params": {
      "additionalProperty": "webpack5"
    },
    "message": "must NOT have additional properties"
  },
  {
    "instancePath": "",
    "schemaPath": "#/additionalProperties",
    "keyword": "additionalProperties",
    "params": {
      "additionalProperty": "projectRoot"
    },
    "message": "must NOT have additional properties"
  },
  {
    "instancePath": "/amp/canonicalBase",
    "schemaPath": "#/properties/amp/properties/canonicalBase/minLength",
    "keyword": "minLength",
    "params": {
      "limit": 1
    },
    "message": "must NOT have fewer than 1 characters"
  },
  {
    "instancePath": "/assetPrefix",
    "schemaPath": "#/properties/assetPrefix/minLength",
    "keyword": "minLength",
    "params": {
      "limit": 1
    },
    "message": "must NOT have fewer than 1 characters"
  },
  {
    "instancePath": "/basePath",
    "schemaPath": "#/properties/basePath/minLength",
    "keyword": "minLength",
    "params": {
      "limit": 1
    },
    "message": "must NOT have fewer than 1 characters"
  },
  {
    "instancePath": "/experimental/outputFileTracingRoot",
    "schemaPath": "#/properties/experimental/properties/outputFileTracingRoot/minLength",
    "keyword": "minLength",
    "params": {
      "limit": 1
    },
    "message": "must NOT have fewer than 1 characters"
  },
  {
    "instancePath": "/generateEtags",
    "schemaPath": "#/properties/generateEtags/isFunction",
    "keyword": "isFunction",
    "params": {},
    "message": "must pass \"isFunction\" keyword validation"
  },
  {
    "instancePath": "/i18n",
    "schemaPath": "#/properties/i18n/type",
    "keyword": "type",
    "params": {
      "type": "object"
    },
    "message": "must be object"
  }
]
See more info here: https://nextjs.org/docs/messages/invalid-next-config

next.config.js


/** @type {import('next').NextConfig} */
const { withExpo } = require("@expo/next-adapter");
const withFonts = require("next-fonts");
const withPlugins = require("next-compose-plugins");
const withTM = require("next-transpile-modules")([
  "react-native-web",
  "react-native-svg",
  "native-base",
]);

const nextConfig = {
  reactStrictMode: true,
  images: {
    domains: [
      "s3-eu-west-1.amazonaws.com",
      "7834446d6472debd8aae-e02563a4b5a029234d332b60ea74b60c.ssl.cf3.rackcdn.com",
      "picsum.photos",
    ],
  },
};

module.exports = withPlugins(
  [withTM, [withFonts, { projectRoot: __dirname }], [withExpo, { projectRoot: __dirname }]],
  nextConfig
);

EuanGwd-AndDigital avatar Aug 05 '22 08:08 EuanGwd-AndDigital

Hi @EuanGwd-AndDigital, Thanks for reporting the issue. We are looking into this issue. We will soon provide support for react 18 and next 12. Please add any additional information you can which will help us.

Viraj-10 avatar Aug 09 '22 06:08 Viraj-10

@Viraj-10 Is there any rc patch or alpha build now? Is it possible to get support for react 18 before the release of the new official version of your package?

coprocoder avatar Aug 09 '22 08:08 coprocoder

Hi @Viraj-10, my team would also be interested in this topic. I did some experiments with the current version on native-base with react 18, and it seems to work mostly. Mainly we found an issue if you put an Input in a Modal and then use the Input from a mobile device.

Switching to Next.js 12.2 fails. Apart from the warnings which are already listed in this issue description I'm getting an error related to the _document.js:

[    ] info  - Generating static pages (0/3)
Error occurred prerendering page "/404". Read more: https://nextjs.org/docs/messages/prerender-error
Error: "Document.getInitialProps()" should resolve to an object with a "html" prop set with a valid html string
    at loadDocumentInitialProps (/home/christian/Projects/nativebase-nextjs-input/node_modules/next/dist/server/render.js:680:23)
    at async renderDocument (/home/christian/Projects/nativebase-nextjs-input/node_modules/next/dist/server/render.js:763:43)
    at async renderToHTML (/home/christian/Projects/nativebase-nextjs-input/node_modules/next/dist/server/render.js:801:28)
    at async /home/christian/Projects/nativebase-nextjs-input/node_modules/next/dist/export/worker.js:251:36
    at async Span.traceAsyncFn (/home/christian/Projects/nativebase-nextjs-input/node_modules/next/dist/trace/trace.js:79:20)

Error occurred prerendering page "/500". Read more: https://nextjs.org/docs/messages/prerender-error
Error: "Document.getInitialProps()" should resolve to an object with a "html" prop set with a valid html string
    at loadDocumentInitialProps (/home/christian/Projects/nativebase-nextjs-input/node_modules/next/dist/server/render.js:680:23)
    at async renderDocument (/home/christian/Projects/nativebase-nextjs-input/node_modules/next/dist/server/render.js:763:43)
    at async renderToHTML (/home/christian/Projects/nativebase-nextjs-input/node_modules/next/dist/server/render.js:801:28)
    at async /home/christian/Projects/nativebase-nextjs-input/node_modules/next/dist/export/worker.js:251:36
    at async Span.traceAsyncFn (/home/christian/Projects/nativebase-nextjs-input/node_modules/next/dist/trace/trace.js:79:20)

Error occurred prerendering page "/". Read more: https://nextjs.org/docs/messages/prerender-error
Error: "Document.getInitialProps()" should resolve to an object with a "html" prop set with a valid html string
    at loadDocumentInitialProps (/home/christian/Projects/nativebase-nextjs-input/node_modules/next/dist/server/render.js:680:23)
    at async renderDocument (/home/christian/Projects/nativebase-nextjs-input/node_modules/next/dist/server/render.js:763:43)
    at async renderToHTML (/home/christian/Projects/nativebase-nextjs-input/node_modules/next/dist/server/render.js:801:28)
    at async /home/christian/Projects/nativebase-nextjs-input/node_modules/next/dist/export/worker.js:251:36
    at async Span.traceAsyncFn (/home/christian/Projects/nativebase-nextjs-input/node_modules/next/dist/trace/trace.js:79:20)
info  - Generating static pages (3/3)

My playground for this would be available under: https://github.com/liebharc/nativebase-nextjs-input

Let me know if there is anything more concrete, which would help you guys.

liebharc avatar Aug 09 '22 16:08 liebharc

Hi @EuanGwd-AndDigital, We have released v3.4.12-alpha.1 for react-native-web 0.18 and expo SDK 46 support. #5075

Viraj-10 avatar Aug 12 '22 06:08 Viraj-10

@Viraj-10 the upgrade of react-native-web and expo hasn't fixed the compatibility issue with Next 12.2.x As described above there seems to be some changes in _document and other places which breaks the Next compilation.

dohomi avatar Aug 14 '22 06:08 dohomi

@Viraj-10 , apologies if this doesn't belong in this discussion, but since you've mentioned 3.4.12 and react-native-web: The latest native-base with react-native-web gives an error:

Module not found: Can't resolve 'react-native-web/dist/exports/StyleSheet/createCompileableStyle'

Steps to reproduce:

  1. git checkout https://github.com/liebharc/nativebase-nextjs-input
  2. cd nativebase-nextjs-input
  3. pnpm run dev
  4. visit localhost:3000

liebharc avatar Aug 14 '22 19:08 liebharc

@liebharc 3.4.12 includes not changes made in v3.4.12-alpha.1 - thats quite confusing but the PR is not merged into master yet. @Viraj-10 it might be better to use a different name for PR pre-releases which are not connecting to SEMVER versioning because me and a few other users bumped into the same issue that we though 3.4.12 will include the alpha.1 changes.

dohomi avatar Aug 15 '22 01:08 dohomi

@dohomi , ah thanks for the clarification. I was able to get this combination running:

  • native-base 3.4.12-alpha.1
  • react: 18.2.0
  • react-dom: 18.0.0
  • react-native: 0.69.4
  • react-native-web: 0.18.7
  • next: 12.2.1

For this I removed the native base adapter for the moment and changed my _document.js to:

import { getInitialProps } from '@expo/next-adapter/document';
import Document, { Html, Head, Main, NextScript } from 'next/document';
import React from 'react';

class CustomDocument extends Document {
  render() {
    return (
      <Html style={{ height: '100%' }}>
        <Head>
          <meta httpEquiv="X-UA-Compatible" content="IE=edge" />
        </Head>
        <body style={{ height: '100%', overflow: 'hidden' }}>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

// Import the getInitialProps method and assign it to your component to ensure the react-native-web styles are used.
CustomDocument.getInitialProps = getInitialProps;

export default CustomDocument;

There are two issues I found with this:

  1. "Select" components running in android native throw an error: TypeError: undefined is not an object (evaluating 'props.getItem')
  2. "Input" components inside of Modals running in next.js behave weird if I enter text on my phone. E.g. enter "student" in the Input, press the auto-completion for "students" and you get "studentstudents" while it should be just "students"

liebharc avatar Aug 15 '22 07:08 liebharc

@Viraj-10 Thank you for your update, I have tried the v3.4.12-alpha.1 you suggested, there might be an issue with the @expo/next-adapter

When spinning up a fresh new NextJS app with the documentation, https://docs.nativebase.io/install-next provided, the following error occurs: Screenshot 2022-08-19 at 10 48 42

yarn run v1.22.19
$ next dev
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
error - Failed to load next.config.js, see more info here https://nextjs.org/docs/messages/next-config-error
Error: Cannot find module '@expo/config/paths'
Require stack:
- /Users/euangreenwood/Development/native-base-test/node_modules/@expo/next-adapter/build/withExpo.js
- /Users/euangreenwood/Development/native-base-test/node_modules/@expo/next-adapter/build/index.js
- /Users/euangreenwood/Development/native-base-test/next.config.js
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
    at Function.mod._resolveFilename (/Users/euangreenwood/Development/native-base-test/node_modules/next/dist/build/webpack/require-hook.js:27:32)
    at Function.mod._resolveFilename (/Users/euangreenwood/Development/native-base-test/node_modules/next/dist/build/webpack/require-hook.js:27:32)
    at Function.Module._load (node:internal/modules/cjs/loader:778:27)
    at Module.require (node:internal/modules/cjs/loader:1005:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at Object.<anonymous> (/Users/euangreenwood/Development/native-base-test/node_modules/@expo/next-adapter/build/withExpo.js:3:17)
    at Module._compile (node:internal/modules/cjs/loader:1105:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
    at Module.load (node:internal/modules/cjs/loader:981:32) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/Users/euangreenwood/Development/native-base-test/node_modules/@expo/next-adapter/build/withExpo.js',
    '/Users/euangreenwood/Development/native-base-test/node_modules/@expo/next-adapter/build/index.js',
    '/Users/euangreenwood/Development/native-base-test/next.config.js'
  ]
}
error Command failed with exit code 1.

Package.json

{
  "name": "native-base-test",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "native-base": "3.4.12-alpha.1",
    "next": "12.2.5",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "react-native-safe-area-context": "3.3.2",
    "react-native-svg": "12.1.1",
    "react-native-web": "0.18"
  },
  "devDependencies": {
    "@expo/next-adapter": "^4.0.12",
    "@types/node": "18.7.6",
    "@types/react": "18.0.17",
    "@types/react-dom": "18.0.6",
    "eslint": "8.22.0",
    "eslint-config-next": "12.2.5",
    "next-compose-plugins": "^2.2.1",
    "next-fonts": "^1.5.1",
    "next-transpile-modules": "^9.0.0",
    "typescript": "4.7.4"
  }
}

next.config.js

/** @type {import('next').NextConfig} */

const { withExpo } = require("@expo/next-adapter");
const withFonts = require("next-fonts");
const withPlugins = require("next-compose-plugins");
const withTM = require("next-transpile-modules")([
  "react-native-web",
  "react-native-svg",
  "native-base",
  "react-native-svg",
]);

const nextConfig = {
  reactStrictMode: true,
  swcMinify: true,
};

module.exports = withPlugins(
  [withTM, [withFonts, { projectRoot: __dirname }], [withExpo, { projectRoot: __dirname }]],
  nextConfig
);

EuanGwd-AndDigital avatar Aug 19 '22 09:08 EuanGwd-AndDigital

Is there any news on this? I'm trying to setup a project with the latest next (example template app is outdated) and native base 3.14.8, and it's still breaking a lot :/

JaccoGoris avatar Oct 13 '22 15:10 JaccoGoris

Hi All, for next 12.2 and react 18.2 support please update your native-base package to v3.4.19. Replace your _document.js with the following code.

import React, { Children } from "react";
import NextDocument, { Html, Head, Main, NextScript } from "next/document";
import { AppRegistry } from "react-native-web";
import { getStyleElement as getResponsiveQueryStyleElement } from "native-base";
// Force Next-generated DOM elements to fill their parent's height
const normalizeNextElements = `
  html, body, #__next {
    width: 100%;
    /* To smooth any scrolling behavior */
    -webkit-overflow-scrolling: touch;
    margin: 0px;
    padding: 0px;
    /* Allows content to fill the viewport and go beyond the bottom */
    min-height: 100%;
  }
  #__next {
    flex-shrink: 0;
    flex-basis: auto;
    flex-direction: column;
    flex-grow: 1;
    display: flex;
    flex: 1;
  }
  html {
    scroll-behavior: smooth;
    -webkit-text-size-adjust: 100%;
    height: 100%;
  }
  body {
    display: flex;
    overflow-y: auto;
    overscroll-behavior-y: none;
    text-rendering: optimizeLegibility;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    -ms-overflow-style: scrollbar;
  }
`;

export async function getInitialProps({ renderPage }) {
  AppRegistry.registerComponent("Main", () => Main);
  const { getStyleElement } = AppRegistry.getApplication("Main");
  const page = renderPage();
  const styles = [
    // eslint-disable-next-line react/jsx-key
    <style dangerouslySetInnerHTML={{ __html: normalizeNextElements }} />,
    getStyleElement(),
    getResponsiveQueryStyleElement(),
  ];
  return { ...page, styles: Children.toArray(styles) };
}
class Document extends NextDocument {
  render() {
    return (
      <Html>
        <Head />
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}
export default Document;

Viraj-10 avatar Oct 21 '22 06:10 Viraj-10

same error after update native-base, see this repo for reproductible error https://github.com/lobor/nativebase-nextjs

lobor avatar Oct 25 '22 15:10 lobor

I found a workaround. The problem is server side renderer (SSR), so load NativeBaseProvider in browser and not in server

// _app.tsx
import "../styles/globals.css";
import React, { useEffect, useState } from "react";
import { NativeBaseProvider } from "native-base";

function MyApp({ Component, pageProps }) {
  const [state, setState] = useState(false);
  useEffect(() => {
    if (typeof window !== "undefined" && !state) {
      setState(true);
    }
  }, []);
  return state ? (
    <NativeBaseProvider>
      <Component {...pageProps} />
    </NativeBaseProvider>
  ) : null;
}

export default MyApp;

lobor avatar Oct 26 '22 06:10 lobor

Hi @lobor, you need to pass isSSR prop to NativeBaseProvider.

Viraj-10 avatar Oct 26 '22 07:10 Viraj-10

I have same error with isSSR

lobor avatar Oct 26 '22 11:10 lobor

I managed to workaround this by installing @expo/config in my repo, e.g. yarn add @expo/config so I'm guessing @expo/next-adapter is missing that as a dependency?

benmoses-equineregister avatar Nov 23 '22 07:11 benmoses-equineregister

I found a workaround. The problem is server side renderer (SSR), so load NativeBaseProvider in browser and not in server

// _app.tsx
import "../styles/globals.css";
import React, { useEffect, useState } from "react";
import { NativeBaseProvider } from "native-base";

function MyApp({ Component, pageProps }) {
  const [state, setState] = useState(false);
  useEffect(() => {
    if (typeof window !== "undefined" && !state) {
      setState(true);
    }
  }, []);
  return state ? (
    <NativeBaseProvider>
      <Component {...pageProps} />
    </NativeBaseProvider>
  ) : null;
}

export default MyApp;

This is not a real workaround as it will prevent any SSR. Why use NextJs in that case?

cgorrieri avatar Jan 03 '23 14:01 cgorrieri

I use Nextjs for the easy configuration. it's very simple, not created router, wrapper, ... all in one. SEO in not a problem

we have chosen tamagui for design system, more light, ssr compatible and more simple

lobor avatar Jan 04 '23 21:01 lobor