Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support NextJS 13 /app directory server-side rendering? #6475

Closed
3 tasks done
ThomasAunvik opened this issue Oct 27, 2022 · 60 comments · Fixed by #6646
Closed
3 tasks done

Support NextJS 13 /app directory server-side rendering? #6475

ThomasAunvik opened this issue Oct 27, 2022 · 60 comments · Fixed by #6646
Labels

Comments

@ThomasAunvik
Copy link

Prerequisites

Describe the bug

React-Bootstrap tries to use React.createContext on server-side?

error - (sc_server)\node_modules\react-bootstrap\cjs\ThemeProvider.js (24:40) @ eval
error - TypeError: React.createContext is not a function
    at eval (webpack-internal:///(sc_server)/./node_modules/react-bootstrap/cjs/ThemeProvider.js:62:42)
    at Object.(sc_server)/./node_modules/react-bootstrap/cjs/ThemeProvider.js (C:\project\.next\server\app\page.js:2495:1)    
    at __webpack_require__ (C:\project\.next\server\webpack-runtime.js:33:42)
    at eval (webpack-internal:///(sc_server)/./node_modules/react-bootstrap/cjs/Accordion.js:8:22)
    at Object.(sc_server)/./node_modules/react-bootstrap/cjs/Accordion.js (C:\project\.next\server\app\page.js:1351:1)        
    at __webpack_require__ (C:\project\.next\server\webpack-runtime.js:33:42)
    at eval (webpack-internal:///(sc_server)/./node_modules/react-bootstrap/cjs/index.js:5:41)
    at Object.(sc_server)/./node_modules/react-bootstrap/cjs/index.js (C:\project\.next\server\app\page.js:2682:1)
    at __webpack_require__ (C:\project\.next\server\webpack-runtime.js:33:42)
    at eval (webpack-internal:///(sc_server)/./app/page.tsx:6:73) {
  type: 'TypeError',
  page: '/'
}

Expected behavior

To render out a component

To Reproduce

  1. Create a NextJS app npx create-next-app@latest --ts
  2. Update next.config.js to use appDir
/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  swcMinify: true,
  experimental: {
    appDir: true,
  }
}

module.exports = nextConfig
  1. Delete Pages Folder
  2. Create file in app/page.tsx with content:
import { Button } from "react-bootstrap";

const Page = () => {
    return <Button>Button</Button>
}

export default Page;
  1. npm run dev
  2. Go to site and recieve error.

Reproducible Example

https://codesandbox.io/p/sandbox/bold-neco-p5zv6j

Screenshots

No response

What operating system(s) are you seeing the problem on?

Windows

What browser(s) are you seeing the problem on?

Firefox

What version of React-Bootstrap are you using?

2.5.0

What version of Bootstrap are you using?

5.2.2

Additional context

vercel/next.js#41929

@Venipa
Copy link

Venipa commented Oct 28, 2022

@ThomasAunvik
for now
image

Edit: add any library to the externals that requires react/client context

@information-security
Copy link

Hey @Venipa,

Your workaround does not work when the root layout is an async function. The following error is raised in that case:
TypeError: Cannot read properties of null (reading 'useContext')

Reproducible Example

Any idea why is this happening and how to fix this?

@Venipa
Copy link

Venipa commented Nov 22, 2022

Hey @Venipa,

Your workaround does not work when the root layout is an async function. The following error is raised in that case: TypeError: Cannot read properties of null (reading 'useContext')

Reproducible Example

Any idea why is this happening and how to fix this?

probably due to app dir is still experimental and external packages not (yet) supported in async root layout (or in general async react components).

@information-security
Copy link

Dear @Venipa,

Thanks for your reply.

Although you are most probably right about the appDir being in the experimental phase and the problem is partially due to that, I guess there is still something special about react-bootstrap package that is causing this behavior. I'm saying this mainly because of two reasons:

  1. External packages are supported in async root layout. At least they are partially supported.
  2. I didn't have the same problem with my own test (simple) package

However, I might be wrong as in fact, the docs around the new next-js feature are not mature, hence, I might not be considering everything.

@petero-dk
Copy link

I have created a WIP PR that makes react-bootstrap work with the appDir: #6532 it does require some polish before being final, any suggestions or assistance would be delightful - it can currently be considered a proof of concept

@DanielFortuyn
Copy link

I could not get your PR to work, is there anyone who is either working on this or making some progress with this issue. I would really like to test the new SSR functionalities of next 13 with bootstrap.

@DanielFortuyn
Copy link

Is there any ticket where we track the progress with regard to the the appDir, because this ticket is closed, but the issue seems to persist and the PR hasn't been completed yet and is missing some components.

@kyletsang kyletsang reopened this Feb 14, 2023
@rjantoine
Copy link

The issue with React-Bootstrap is that everything is considered a Client Component. Even trying to add a column with the Col component, React-Bootstrap pulls in code for potential modals. This requires you to add 'use client' to the top of any page using almost any React-Bootstrap component, which means it is no longer rendered on the server, but client side, which is probably not what you want. I have been using the class names for anything server side (such as

instead of ), and for anything client side, that a visitor needs to interact with, such as a menu bar, I wrap it in a custom component that has 'use client' at the top.

So for example, for my menu, I do the following:

In app/layout.js

import MainMenu from '../components/MainMenu.js'

export default function RootLayout({children}) {
    return <html>
       <head />
       <body>
          <MainMenu />
          {children}
       </body>
    </html>
}

in components/MainMenu.js

'use client'

import { Container, Nav, Navbar, NavDropdown, SSRProvider } from 'react-bootstrap'

export default function MainMenu() {
  return <SSRProvider>
    <Navbar bg="light" expand="lg">
      <Container>
        <Navbar.Brand href="#home">React-Bootstrap</Navbar.Brand>
        <Navbar.Toggle aria-controls="basic-navbar-nav" />
        <Navbar.Collapse id="basic-navbar-nav">
          <Nav className="me-auto">
            <Nav.Link href="#home">Home</Nav.Link>
            <Nav.Link href="#link">Link</Nav.Link>
          </Nav>
        </Navbar.Collapse>
      </Container>
    </Navbar>
  </SSRProvider>
}

I'm not sure if the SSRProvider in the leaves instead of the root will cause me issues later, but for now, this is working.

@ddcrobert
Copy link

The issue with React-Bootstrap is that everything is considered a Client Component. Even trying to add a column with the Col component, React-Bootstrap pulls in code for potential modals. This requires you to add 'use client' to the top of any page using almost any React-Bootstrap component, which means it is no longer rendered on the server, but client side, which is probably not what you want. I have been using the class names for anything server side (such as

instead of ), and for anything client side, that a visitor needs to interact with, such as a menu bar, I wrap it in a custom component that has 'use client' at the top.
So for example, for my menu, I do the following:

In app/layout.js

import MainMenu from '../components/MainMenu.js'

export default function RootLayout({children}) {
    return <html>
       <head />
       <body>
          <MainMenu />
          {children}
       </body>
    </html>
}

in components/MainMenu.js

'use client'

import { Container, Nav, Navbar, NavDropdown, SSRProvider } from 'react-bootstrap'

export default function MainMenu() {
  return <SSRProvider>
    <Navbar bg="light" expand="lg">
      <Container>
        <Navbar.Brand href="#home">React-Bootstrap</Navbar.Brand>
        <Navbar.Toggle aria-controls="basic-navbar-nav" />
        <Navbar.Collapse id="basic-navbar-nav">
          <Nav className="me-auto">
            <Nav.Link href="#home">Home</Nav.Link>
            <Nav.Link href="#link">Link</Nav.Link>
          </Nav>
        </Navbar.Collapse>
      </Container>
    </Navbar>
  </SSRProvider>
}

I'm not sure if the SSRProvider in the leaves instead of the root will cause me issues later, but for now, this is working.

Indeed, most of the components are using the ThemeProvider, making this lib client-only (in its current form).
Thus, I dropped react-bootstrap from my project, kept bootstrap stylesheet, then started rewriting more RSC-friendly components.

@DanielFortuyn
Copy link

Interesting, I wonder what the long term way forward is. It sounds like that approach could be a new project in itself as it sounds like react-bootstrap is just not compatible with this use case.

@gunslingor
Copy link

gunslingor commented Feb 28, 2023

I think I am running into this issue. We are beginning the process of converting a 100k line haml project into something modern; we picked nextJS for the SSR features and react-bootstrap for its well tested prebuilt components. We come to find out SSR doesn't seem to work with ANY pre built component libraries. Even next UI doesn't support it on the server: https://nextui.org/docs/guide/nextui-plus-nextjs. None appear to.

But doesn't this end result effectively make SSR completely useless for the most common applications? If your writing a blog and you want to start rendering on the backend, you can't use the same components you were using before and there are no replacement components available even if your okay with the different styles and customizing; so you have to build custom primitives on the backside and probably wire everything with jquery instead of react (which SSR seems to handle fine and is basically doing the same thing as react-bootstrap as far as the browser is concerned).

Fundamentally, I think this really is a NextJS issue, not an issue with react-bootstrap. I really don't know anything about the internals of nextJS, but I get the impression it has wrapped a lot of react functionality to work on both the server and the client by varying the rendering methods that are generated depending on where it is rendered. It seems they need to do the same for state, that maybe this isn't handled well enough on next SSR. For SSR generated states, I think it obviously wouldn't manage state on the backside, but I think the backside should be able to generate componentized dynamic JS that includes the state for the client to manage.

Bottom line, for the first conversations we tried to make a frontend page with react-bootstrap button and it worked but we couldn't get it working with SSR, no prebuilt components work on SSR as far as I can tell, it only seems to handle uncontrolled components. So I think it only works with pure CSS styles and JS.

Another reason I think this is NextJS's issue, no the lib manufacturers, is that the web based community just spent the last decade or so explicitly separating front and backend code for the advantages we thought we had, now nextJS is trying to shove them back together to retain some of the benefits. It uses JS/TS specifically to keep the language the same on the front and backend, and to avoid having to learn a traditional backend language I guess. But I can use react-bootstrap and PHP or other traditional backends without issue, I specify how its rendered and when. Even spring-boot, I hear, has a SSR method that does work with react-bootstrap as far as I can tell.

So I'm not really sure where to go next... I guess we will use the modern next JS app folder and just separate backend frontend code in various data/view folders that can be hopefully be easily moved to be more isolated if nextJS SSR goes the way of the dinosaurs.

I think you guys really do need to make this work with the most common unmodified component libraries.

image

@rjantoine
Copy link

rjantoine commented Feb 28, 2023 via email

@HaiderMalik12
Copy link

I am getting the same issue. I am using new app feature with react-bootstrap package
I am getting this error
When server rendering, you must wrap your application in an <SSRProvider> to ensure consistent ids are generated between the client and server.

@DanielFortuyn
Copy link

The root of the issue is that code exists in two forms in React: Server-side code (any file that doesn’t return a JSX object) Client-side code (any file that does return a JSX object), that is not pre-rendered in any way. It’s just packaged up and send to the client browser to deal with. NextJS can only pre-render pages that return a JSX object whose javascript can be run at build time. To run any of the javascript client side, it either needs to be vanilla javascript (or jQuery) that can be put into a script tag, or a react file that starts with ‘use client’. So the trick is to build as much of the site with code that can run at build time. Anything that needs to run in the client’s browser needs to be broken out into a separate component. This way, NextJS can pre-render any page that returns a JSX object ahead of time, unless it has ‘use client’ as its first line. Since most all UI requires user interaction, it can’t be pre-rendered, so it needs to be put in its own file. Eventually, these libraries will put ‘use client’ themselves at the beginning of every component that needs to run in the browser, but until then, we have to make separate components ourselves.

On Feb 28, 2023, at 9:42 AM, gunslingor @.***> wrote: I think I am running into this issue. We are beginning the process of converting a 100k line haml project into something modern; we picked nextJS for the SSR features and react-bootstrap for its well tested prebuilt components. We come to find out SSR doesn't seem to work with ANY pre built component libraries. Even next UI doesn't support it on the server: https://nextui.org/docs/guide/nextui-plus-nextjs. None appear to. But doesn't this end result effectively make SSR completely useless for the most common applications? If your writing a blog and you want to start rendering on the backend, you can't use the same components you were using before and there are no replacement components available even if your okay with the different styles and customizing; so you have to build custom primitives on the backside and probably wire everything with jquery instead of react (which SSR seems to handle fine and is basically doing the same thing as react-bootstrap as far as the browser is concerned). Fundamentally, I think this really is a NextJS issue, not an issue with react-bootstrap. I really don't know anything about the internals of nextJS, but I get the impression it has wrapped a lot of react functionality to work on both the server and the client by varying the rendering methods that are generated depending on where it is rendered. It seems they need to do the same for state, that maybe this isn't handled well enough on next SSR. For SSR generated states, I think it obviously wouldn't manage state on the backside, but I think the backside should be able to generate componentized dynamic JS that includes the state for the client to manage. Bottom line, for the first conversations we tried to make a frontend page with react-bootstrap button and it worked but we couldn't get it working with SSR, no prebuilt components work on SSR as far as I can tell, it only seems to handle uncontrolled components. So I think it only works with pure CSS styles and JS. Another reason I think this is NextJS's issue, no the lib manufacturers, is that the web based community just spent the last decade or so explicitly separating front and backend code for the advantages we thought we had, now nextJS is trying to shove them back together to retain some of the benefits. It uses JS/TS specifically to keep the language the same on the front and backend, and to avoid having to learn a traditional backend language I guess. But I can use react-bootstrap and PHP or other traditional backends without issue, I specify how its rendered and when. Even spring-boot, I hear, has a SSR method that does work with react-bootstrap as far as I can tell. So I'm not really sure where to go next... I guess we will use the modern next JS app folder and just separate backend frontend code in various data/view folders that can be hopefully be easily moved to be more isolated if nextJS SSR goes the way of the dinosaurs. I think you guys really do need to make this work with the most common unmodified component libraries.

So reading the above it seems like it might be a good idea to create an issue on the nextjs project itself. Or is there already an issue tracking this on the next project?

@rjantoine
Copy link

rjantoine commented Mar 3, 2023 via email

@arenddeboer
Copy link

@gunslingor react-bootstrap + Next.js 13 still support SSR, I think you are confusing React Server Components with Server Side Rendering. Anyway I agree with @rjantoine, React and Next.js are prioritizing static content with Next.js 13. If your project is interactive and does (form) mutations, the sacrifices made to support this direction may not be worth it.

@DanielFortuyn
Copy link

Just to keep you guys informed, my team did some successful tests with the reactstrap package. Apparently the migration wasn't too bad either. Just FYI.

@gunslingor
Copy link

@gunslingor react-bootstrap + Next.js 13 still support SSR, I think you are confusing React Server Components with Server Side Rendering. Anyway I agree with @rjantoine, React and Next.js are prioritizing static content with Next.js 13. If your project is interactive and does (form) mutations, the sacrifices made to support this direction may not be worth it.

I was just trying to make a login form. Zero react-bootstrap components, or any other lib I tried for that matter, didn't work in ssr. It was a login page, never intended for complex form dynamics involving state, just a login page. I found the only way to SSR a login page is to rebuilt primitives like Button, Form, etc... restyling a style that already exists.

If I have the option to use local, I should probably be given the option to "use view" so common libs, view layout and styles only, are still usable.

I just can imagine a use case where a blog, the prime target for SSR, says okay let's rebuild all the primitives to support SSR because they don't work now and never will.

@jquense
Copy link
Member

jquense commented Mar 23, 2023

Folks we aren't really going to update RB to work with server components until server components are stable and documented, otherwise it's a moving target we can't hit.

RB components all continue to support normal react server side rendering. The entire react ecosystem depends on using create context for components so I can't imagine Next just doesn't work with most react components for sites, I assume you can tell it not to treat the components as RSCs and just do the old boring thing of rendering them on the server and hydrating

@makinbacon21
Copy link

makinbacon21 commented Apr 3, 2023

Folks we aren't really going to update RB to work with server components until server components are stable and documented, otherwise it's a moving target we can't hit.

RB components all continue to support normal react server side rendering. The entire react ecosystem depends on using create context for components so I can't imagine Next just doesn't work with most react components for sites, I assume you can tell it not to treat the components as RSCs and just do the old boring thing of rendering them on the server and hydrating

I mean they're pretty stable and well-documented at the moment as far as I can tell...we've been using them for a while now and have no issues other than inability to use react-boostrap. As a matter of fact we have had no issues with any other frameworks in server components. I hope this is resolved soon--react-bootstrap is a lot better than alternatives like reactstrap for a lot of stuff.

@rjantoine
Copy link

The main issue is that every inch of the react-bootstrap code uses context to store the theme. Context is done client side, not server side, and requires 'use client' in the new RSC paradigm. To be compatible with Next JS server components, things like themes that are likely to be a constant should be stored in an environment variable or config file, instead of in a context. The only things that should use state or context should be variables that can potentially change through user interaction. Since the react-bootstrap stream has indicated that they don't want to change anything until RSCs are stable, likely meaning when NextJS 13 is out of beta, the easiest solution is to put 'use client' at the top of the page.tsx file or to wrap any react-bootstrap code it in a ClientComponent wrapper.

components/ClientComponent.js

'use client';

export default function ClientComponent({children}) {
  return (
    <>
      {children}
    </>
  );
}

app/[slug]/page.js

const Page = () => <ClientComponent>
   {/*... insert code using react-bootstrap components here ... */}
</Container>

export default Page

@makinbacon21
Copy link

Well not Page, as Page must be a server component, but it appears you can set a server component as the child of a client component (or pass it through as a prop). Docs: https://beta.nextjs.org/docs/rendering/server-and-client-components#importing-server-components-into-client-components
This should work for now...we can just do as you suggest and put react bootstrap components only in client components, and just have a ton of wrappers.

@ehsangazar
Copy link

Well, SSR not working with NextJS 13.3.0!

@makinbacon21
Copy link

works for me...we're now using the nested component strat and it's working just fine. Would be cool to do full ssr with react bootstrap but letting the clients handle the bulk of the ui is working out alright.

@starlight-akouri
Copy link

Kinda completely defeats the purpose and performance improvements that React Server Components are supposed to bring. Anybody know if react-bootstrap is going to plan on implementing the Context differently in the future? Or should I try to migrate to something else for a new project?

@rjantoine
Copy link

rjantoine commented May 10, 2023 via email

@jquense
Copy link
Member

jquense commented Jun 3, 2023

Folks, PRs welcome. If it's clear to you that RSC are awesome and supporting them is easy and straightforward, please send the PR. We would really love that, very seriously. Otherwise, please wait until we have time to devote to figuring out how to add support in a way that supports RBs diverse and expansive user base.

Going to lock the convo now since it's mostly folks +1-ing which isn't super helpful.

@react-bootstrap react-bootstrap locked and limited conversation to collaborators Jun 3, 2023
@react-bootstrap react-bootstrap unlocked this conversation Jun 3, 2023
@jquense
Copy link
Member

jquense commented Jun 3, 2023

@WalterOkumu and others, "use client" components are still SSR'd and produce HTML that is sent to the client. They work just like SSR always has, and react bootstrap components are all SSR compatible. You don't need the new server components to get SEO. The new RSC stuff isn't a SEO solution it's a js bundle reduction improvement. Folks are conflating features or misunderstanding what RSC is compared to "normal" SSR.

@cduff
Copy link

cduff commented Jun 18, 2023

@jquense re: https://nextjs.org/docs/getting-started/react-essentials#third-party-packages

Would the first and easiest thing be to just add "use client" directives inside react-bootstrap where necessary? This would allow it to be used in RSC without having to create wrapper components.

@jquense
Copy link
Member

jquense commented Jun 18, 2023

yes we can do that, ideally as part of the build step so we don't have to remember to do it for every new file

@devmuhnnad
Copy link
Contributor

devmuhnnad commented Jun 18, 2023

Hi @jquense,
So is the best solution for the moment to support NextJS appDir, to add "use client" for all react-bootstrap components?
can I create a PR for that?

@cduff
Copy link

cduff commented Jun 18, 2023

If I understand correctly, the simplest thing initially would be to put a single "use client" at the top of https://github.com/react-bootstrap/react-bootstrap/blob/master/src/index.tsx, especially if all the components currently depend on client context.

Later, optimisations could be made to push "use client" further down the component module graph as appropriate.

Note that react have

reached consensus with our partners to go with the "use client" convention.

Source: https://react.dev/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023#react-server-components

@OttoG
Copy link

OttoG commented Jul 11, 2023

@WalterOkumu and others, "use client" components are still SSR'd and produce HTML that is sent to the client. They work just like SSR always has, and react bootstrap components are all SSR compatible. You don't need the new server components to get SEO. The new RSC stuff isn't a SEO solution it's a js bundle reduction improvement. Folks are conflating features or misunderstanding what RSC is compared to "normal" SSR.

This is all true, but I would not say that bundle reduction is the main benefit that React Server Components provide. Rather, the main reason to use Server Components is that they make it possible to build components that can run code that belongs on the server side, such as authenticated API requests, database requests, etc. Considering the “fetch data where it's used” recommendation – https://nextjs.org/docs/app/building-your-application/data-fetching – it is desirable that client components are only required where they are strictly necessary (because they need to access browser events or similar), as close to the leaf nodes of the page structure as possible.

@alicia-lyu
Copy link

@ThomasAunvik for now image

Edit: add any library to the externals that requires react/client context

This solution is causing issues within the next modules.

Unhandled Runtime Error
Error: Cannot read properties of null (reading 'useRef')
Call Stack
useRef

[next-repo]/node_modules/next/dist/compiled/react/cjs/react.development.js (1764:21)
useUncontrolledProp

[next-repo]/node_modules/uncontrollable/lib/cjs/hook.js (24:38)
<unknown>

[next-repo]/node_modules/uncontrollable/lib/cjs/hook.js (63:32)
Array.reduce

<anonymous>
useUncontrolled

[next-repo]/node_modules/uncontrollable/lib/cjs/hook.js (53:30)
<unknown>

[next-repo]/node_modules/react-bootstrap/cjs/Nav.js (31:43)

More discussions about this issue.

Seems to me that setting experimental in next.config.js is causing code snippets in next module to identify __NEXT_PRIVATE_PREBUNDLED_REACT=="experimental.

An approach that makes more sense to me is to add 'use client' wherever necessary within react-bootstrap module.

@alicia-lyu
Copy link

@ThomasAunvik for now image
Edit: add any library to the externals that requires react/client context

This solution is causing issues within the next modules.

Unhandled Runtime Error
Error: Cannot read properties of null (reading 'useRef')
Call Stack
useRef

[next-repo]/node_modules/next/dist/compiled/react/cjs/react.development.js (1764:21)
useUncontrolledProp

[next-repo]/node_modules/uncontrollable/lib/cjs/hook.js (24:38)
<unknown>

[next-repo]/node_modules/uncontrollable/lib/cjs/hook.js (63:32)
Array.reduce

<anonymous>
useUncontrolled

[next-repo]/node_modules/uncontrollable/lib/cjs/hook.js (53:30)
<unknown>

[next-repo]/node_modules/react-bootstrap/cjs/Nav.js (31:43)

More discussions about this issue.

Seems to me that setting experimental in next.config.js is causing code snippets in next module to identify __NEXT_PRIVATE_PREBUNDLED_REACT=="experimental.

An approach that makes more sense to me is to add 'use client' wherever necessary within react-bootstrap module.

I think it might be helpful to share my temporary solution—wrap react-bootstrap components in a separate file with the "use client" directive:

'use client'

import { PropsWithChildren, ComponentProps } from "react"
import { Button, Col, Container, Nav, Row } from "react-bootstrap"

export function withClient<PropsType extends PropsWithChildren>(
    ComponentToBeWrapped: React.ComponentType<PropsType>
): React.FC<PropsType> {
    function WrappedComponent({children, ...otherProps}: PropsType) {
        return <ComponentToBeWrapped {...otherProps as PropsType}>
            {children}
        </ComponentToBeWrapped>
    }
    return WrappedComponent
}

export const ClientContainer = withClient<ComponentProps<typeof Container>>(Container);
export const ClientCol = withClient<ComponentProps<typeof Col>>(Col);
export const ClientRow = withClient<ComponentProps<typeof Row>>(Row);

export const ClientNav = withClient<ComponentProps<typeof Nav>>(Nav);
export const ClientNavLink = withClient<ComponentProps<typeof Nav.Link>>(Nav.Link);

export const ClientButton = withClient<ComponentProps<typeof Button>>(Button);

ClientNav etc should be good to be imported in a server component. There is no good way to wrap the static field Link in ClientNav, so I just create a ClientNavLink.

I really hope this issue will be resolved from the developer's side, otherwise I won't use react-bootstrap with Next.js applications in the future.

@cduff
Copy link

cduff commented Aug 6, 2023

@alicia-lyu I have a similar workaround, but I think it can be simpler, like:

// client-react-bootstrap.ts
"use client";
export { Col, Container, Offcanvas, Row } from "react-bootstrap";

I then make sure to import any react-bootstrap component from my client-react-bootstrap module.

@kyletsang
Copy link
Member

I just released v2.9.0-beta.1 that should support RSC as best as we could right now. There is a known issue where you can't use the dot notation for components such as Dropdown.Item etc. You would have to import those components separately.

This is tracked here: #6669

Please give it a try and let me know if there are any issues.

@alicia-lyu
Copy link

@alicia-lyu I have a similar workaround, but I think it can be simpler, like:

// client-react-bootstrap.ts
"use client";
export { Col, Container, Offcanvas, Row } from "react-bootstrap";

I then make sure to import any react-bootstrap component from my client-react-bootstrap module.

Yes it works, except that for dot notation components like Nav.Link I need to do this extra step:

export const NavLink = Nav.Link;

It's good to know there is a simpler solution. Thank you!

@alicia-lyu
Copy link

#6669

Looks great. I will reply in your original thread for future issues.

@IamGideonIdoko
Copy link

@alicia-lyu I have a similar workaround, but I think it can be simpler, like:

// client-react-bootstrap.ts
"use client";
export { Col, Container, Offcanvas, Row } from "react-bootstrap";

I then make sure to import any react-bootstrap component from my client-react-bootstrap module.

Yes it works, except that for dot notation components like Nav.Link I need to do this extra step:

export const NavLink = Nav.Link;

It's good to know there is a simpler solution. Thank you!

I think this workaround only works for non-interactive components

Here's what I get when I passed an onClick prop to the react-bootstrap button:

Screenshot 2023-08-13 at 1 03 34 AM

@cduff
Copy link

cduff commented Aug 13, 2023

I think this workaround only works for non-interactive components

@IamGideonIdoko I think that's expected. The same would occur for a basic <button onClick={() => {}} ... in a server component. If you're defining client-side event handlers then you need to mark the module as use client.

@marceloverdijk
Copy link

So probably the best solution for now is to stick with Pages router instead of App router when creating a new app?

@cduff
Copy link

cduff commented Sep 27, 2023

So probably the best solution for now is to stick with Pages router instead of App router when creating a new app?

@marceloverdijk Depends if you then plan to migrate from Pages router to App router in the future. If so, my opinion from experience would be to start with App router and just use a simple workaround for this react-bootstrap issue for now. Adding/removing that workaround will be far less effort than a Pages > App router migration.

@kyletsang
Copy link
Member

Sorry for the delay. I promoted the beta to stable since it appeared to be mostly working. Same caveats apply: #6669

@marceloverdijk
Copy link

Thx for your feedback @cduff .
I tried now with latest 2.9.0 and then indeed I don't need to use the 'use client' anymore.

But I wonder does that impact my generated code when using a SSG ? As much as possible should be generated when exporting and not on the client.

@kyletsang Indeed when upgrading to 2.9.0 I see #6669 happening. Is there a workaround for that?

@cduff
Copy link

cduff commented Sep 27, 2023

@marceloverdijk

Thx for your feedback @cduff . I tried now with latest 2.9.0 and then indeed I don't need to use the 'use client' anymore.

👍

But I wonder does that impact my generated code when using a SSG ? As much as possible should be generated when exporting and not on the client.

I believe #6475 (comment) may be relevant.

@kyletsang Indeed when upgrading to 2.9.0 I see #6669 happening. Is there a workaround for that?

See #6475 (comment).

@meiyingqishi
Copy link

Hi there, @kyletsang .

Next.js components are server-side components by default.(https://nextjs.org/docs/messages/context-in-server-component
When the component used contains client-side APIs such as createContext, an error will be reported. A framework is needed to solve this problem. Solving this problem may be very complicated and requires considering the specific functions of specific components. This will be difficult to solve for a while and will need to be solved slowly over a long period of time in the future.

This problem cannot be solved quickly at present. Developers using React will face a lot of pain. The code they write will be terrible, bad and inelegant. Developers will be very hesitant and usually will not easily decide to use react-bootstrap, but will Looking for other frameworks, Next.js is currently the mainstream of front-end development, app router is the default development method of Next.js, and pages have been eliminated. Currently, the simplest and most direct way is for you to officially add 'use client’ directly to the component. Primer design system also encountered this problem, and they currently solve it in this way.(primer/react#4069 (comment))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.