Reputation: 1234
I am experiencing following error:
Warning: Text content did not match. Server: "But I want to be altered by the client" Client: "Test"
in div (at pages/index.tsx:17)
in div (at pages/index.tsx:6)
in HomePage (at _app.tsx:5)
in MyApp
in Container (created by AppContainer)
in AppContainer
... with the following setup:
A NextJS App Component:
function HomePage() {
return (
<>
<div id="test-div">I am rendered on the server.</div>
<script src="http://localhost:8080/bundle.js"></script>
</>
);
}
export default HomePage;
(Note: The URL http://localhost:8080/bundle.js
assumes webpack-dev-server is running and serving that resource)
The included "example" script:
const element = document.getElementById('test-div') as any;
element.innerHTML = 'But I want to be altered by the client';
In a simple setup I would just have a static html file, declaring a div element and including the "example" script.
But I would like to use NextJS, because I want to render dynamic (SSR) content into the page (eg. Text contents from a cms).
I noticed, that sometimes (if script execution takes some more ms of time), there is no error. Just do something time consuming in the example script.
Another hacky approach is to use setTimeout
in the example script.
I don't want to do that until I know why this is happening:
setTimeout(function() {
const element = document.getElementById('test-div') as any;
element.innerHTML = 'But I want to be altered by the client';
}, 20);
Upvotes: 7
Views: 17954
Reputation: 6603
You can use Next.js Script component to load third-party scripts.
// pages/index.js
import Script from 'next/script'
function Home() {
return (
<>
<Script src="https://www.google-analytics.com/analytics.js" />
</>
)
}
With next/script
, you can define the strategy
property and Next.js will optimize loading for the script.
Browser and document
, window
objects are not available during server-side rendering.
You can initialize scripts that manipulate DOM after React component did mount.
useEffect(() => init(), [])
To add an external script you can do the following:
useEffect(() => require('../babylon.js'), [])
To include a script from another server you can add a script
tag:
useEffect(() => {
const script = document.createElement("script");
script.src = "http://localhost:8080/bundle.js";
script.async = true;
document.body.appendChild(script);
},[])
If you're adding DOM listeners you would also need to do cleanup.
Upvotes: 19