React server component inside a client component in Next 13 - reactjs

I was testing how server and client component interact and came up with something that I don't understand. Here is the code:
// layout.js
"use client";
/* ... imports */
export const Test = createContext();
export default function RootLayout({ children }) {
return (
<html lang="en">
<head />
<body>
<Test.Provider value={"haha"}>
<Header />
{children}
<Footer />
</Test.Provider>
</body>
</html>
);
}
// Header
function Header() {
/* ...imports */
const haha = useContext(Test);
return (
<header>
{haha}
</header>
);
}
Header is a server component, so executed and rendered on the server. But it is still able to access the context which is being provided by the client layout component. How is this possible?

Related

Next.js 13 Server Components > Access Route Segment From Root Layout

Is it possible to access the current selected layout segment from a component placed inside a root layout?
i.e.
export default async function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html>
<head />
<body>
<NavMenu session={session} />
<GlobalHero /> {/* <- This is where I want to access the current route */}
{children}
</body>
</html>
);
}
// importing this causes a runtime error
// Error: Cannot read properties of null (reading 'useContext')
import { useSelectedLayoutSegment } from "next/navigation"
export default function GlobalHero() {
return ( <div> .... </div>)
}

Could not detect external Js file in Helmet

I have started learning React and I was creating the navigation bar.
I have leftNavigationBar defined like this
const LeftNavigationBar = (props) => {
return (
<header className={share.mypage_header} id="leftcolumn">
<Helmet>
<script type="text/babel" src="../../common/js/share.js" />
</Helmet>
</header>
);
};
export default LeftNavigationBar;
but share.js did not detected.
I put require('../../common/js/share.js'); on the top and it started working and code becomes like this
require('../../common/js/share.js');
const LeftNavigationBar = (props) => {
return (
<header className={share.mypage_header} id="leftcolumn">
<Helmet>
<script type="text/babel" src="../../common/js/share.js" />
</Helmet>
</header>
);
};
export default LeftNavigationBar;
I want to know why share.js did not worked when added inside Helmet but worked when added as require on top.
Please help.

Using react context not working as expected in remix react?

Despite having seen working examples of this in non remix projects, it doesn't seem to work in the way I'm implementing it?
I have the following in root.tsx:
export const MyContext = createContext("default");
function Document({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<head>
<Meta />
<Links />
</head>
<body className="root-body">
<MyContext.Provider value="bonjour!">
<Header />
</MyContext.Provider>
{children}
<ScrollRestoration />
<Scripts />
<LiveReload />
<Footer />
</body>
</html>
);
}
export default function App() {
return (
<Document>
<Outlet />
</Document>
);
}
In my <Header/> component I have:
import { useContext } from "react";
import { MyContext } from "~/root";
export const Header = () => {
const result = useContext(MyContext);
console.log(result);
return(null)
}
The result is then that "default" is printed to the console, but surely from my understanding it should be "bonjour"?
Where am I going wrong?
The output on the server console is from Remix SSR. It does appear that the context is not being applied during server rendering. However, it does show up correctly after hydration. Unfortunately it also results in hydration errors (see browser console).
Anyway, that does seem odd. My understanding is that you can use most hooks server side (except for useEffect and useLayoutEffect).
https://codesandbox.io/s/remix-react-context-mzexmt

Error: Target container is not a DOM element ( React/Nextjs)

I have created a context component in React to return a message across all my React pages.
I am getting the error in the subject. Looked at other questions in stackoverflow but none could help me.
Here is the code:
message.js
function Message(props) {
const messageCtx = useContext(MessageBannerContext);
return ReactDOM.createPortal(
<div>
<p>Message</p>
<button>More info</button>
<button onClick={messageCtx.hideMessage}>Ok</button>
</div>,
useEffect(() => {
document.getElementById('message');
}, [])
);
}
export default Message;
_document.js
class MyDocument extends Document {
render() {
return (
<Html>
<Head />
<body>
<Main />
<DeferNextScript />
</body>
<div id="message"></div>
</Html>
);
}
}
export default MyDocument;
Any ideas why I am getting the error in the subject?
Nextjs is run in the server, so the Document Object isn't defined. I've always struggled with that, however you can try a package named jsdom.

How to use React.Component with renderToString method?

I tried to do the server side render using renderToString method.
function handleRender(req, res) {
const html = renderToString(
<Counter />
);
res.send(renderFullPage(html));
}
function renderFullPage(html) {
return `
<!doctype html>
<html>
<head>
<title>React Universal Example</title>
</head>
<body>
<div id="app">${html}</div>
<script src="/static/bundle.js"></script>
</body>
</html>
`
}
If the component like following it works:
Counter.js
const Counter = () => {
function testClick(){
console.log('test');
}
return (
<div>
<div onClick={testClick.bind(this)}>
test
</div>
</div>
);
};
export default Counter;
However, if I change Counter.js into following:
class Counter extends React.Component {
testClick(){
console.log('click');
}
render() {
return (
<div>
<div onClick={this.testClick.bind(this)}>
test btn
</div>
</div>
)
}
}
export default Counter;
It will show errors:
Uncaught Error: locals[0] does not appear to be a `module` object with Hot Module replacement API enabled. You should disable react-transform-hmr in production by using `env` section in Babel configuration.
So how to use React.Component with renderToString method?
I minimize the project and push to Github. Please have a look.
https://github.com/ovojhking/ssrTest/tree/master

Resources