I’m working with a React component that has important logic in its componentDidMount method:
export default class UserWidget {
componentDidMount() {
// DOM modifications happen here via external library
}
render() {
return (
<section>{props.userInfo}</section>
);
}
}
I want to capture a screenshot of this component using Puppeteer, but I need the componentDidMount logic to execute properly. Here’s what I’m trying:
const browserInstance = await puppeteer.launch({ headless: true });
const newPage = await browserInstance.newPage();
const markup = ReactDOMServer.renderToString(<UserWidget userInfo='' />); // This bypasses componentDidMount
await newPage.setContent(markup);
await newPage.screenshot({ path: 'output.png' });
The issue is that server-side rendering with renderToString
doesn’t trigger lifecycle methods. I could use newPage.goto()
instead, but that would require dealing with authentication flows that I’d prefer to skip. Is there a way to pass props directly to the component and still have the lifecycle methods execute properly?
I hit this exact issue with chart components that needed to initialize after mounting. Here’s what worked: create a minimal HTML page with React loaded via CDN, then use page.goto()
with a data URL to skip auth issues. Embed your component props directly in the HTML as JSON and mount everything client-side. Try await page.goto('data:text/html,' + encodeURIComponent(htmlWithEmbeddedComponent))
. This gives you full lifecycle execution without any server requests. The data URL trick’s been rock solid for my screenshot automation - especially when I need DOM manipulation libraries to run properly.
Skip server-side rendering and mount your component in a basic HTML page instead. Set up a simple HTML template with a target div, then use page.addScriptTag()
to inject React and your component code. After that, call page.evaluate()
to mount the component with ReactDOM.render(). This way you get the full client-side lifecycle, including componentDidMount. I’ve done this when testing components that rely on third-party libraries modifying the DOM after mount. Just make sure React runs in the browser context, not server-side.
try using page.evaluate()
to manually trigger your componentDidMount after you set the content. you can access your component via refs or global vars and directly call the lifecycle method. it’s a bit hacky, but it helps if you wanna skip full page loads.