How to render React component with lifecycle methods in Puppeteer?

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.