react-frontload icon indicating copy to clipboard operation
react-frontload copied to clipboard

handling error during server render

Open matthewlein opened this issue 2 years ago • 1 comments

Can you clarify how server rendered errors are handled? I'm trying to raise an error in the frontload to be handled in the node server render block, but I can't seem to catch the error anywhere. It seems like its being swallowed somewhere, but I can't figure it out.

If an error does throw on server render, it is not caught and populated in frontloadMetadata.error, instead it is just thrown and the entire render will fail. Such errors should be caught at the top level in your server render endpoint, and dealt with appropriately for your application.

This sounds like exactly what I want, but from what I can see, frontloadMetadata.error is populated, and the error is being caught.

frontload definitely sees the error

[react-frontload] Error on frontload [WaterbodyDetailLoader:lake-dorr], render pass 0

 RecordNotFoundError: Request failed with status code 404
 [stack trace]
 {
  name: 'RecordNotFoundError',
  url: 'waterbodies/lake-dorr'
} 

The component appears to keep rendering though, I see frontloadMeta.error true logged in the server console from the component:

export const WaterbodyDetailLoader = (props: OwnProps) => {
  const { urlSlug } = props;
  const dispatch = useDispatch();
  const { frontloadMeta } = useFrontload(
    `WaterbodyDetailLoader:${urlSlug}`,
    async () => {
      try {
        const waterbodyRes = await apiV1.waterbodyFetch(urlSlug);
      } catch (e) {
        if (e.response.status === 404) {
          throw new RecordNotFoundError(e.message, e.response.config.url);
        }
        throw e;
      }

      console.log("WaterbodyDetailLoader complete");

      return true;
    }
  );

  console.log("frontloadMeta.error", frontloadMeta.error);

  return <WaterbodyDetailContainer urlSlug={urlSlug} />;
};

Nothing is logged at the catch block of the server rendering block

try {
    const { rendered, data } = await frontloadServerRender({
      frontloadState,
      render: () =>
        renderToString(
          extractor.collectChunks(
            React.createElement(AppServer, {
              location: req.url,
              store,
              routerContext,
              frontloadState,
            })
          )
        ),
    });

    res.send(
      DOCTYPE +
        '\n' +
        renderToString(
          React.createElement(Html, {
            content: rendered,
            store,
            xForwardedFor,
            frontloadData: data,
          })
        )
    );
  } catch (err) {
    console.log('frontload error?', err);
  }

What would you expect to happen with errors in this setup?

Do you happen to have a simple demo site that can be used verify how errors work? I may make one, but if you have one already it would be helpful to rule out app code.

matthewlein avatar Sep 01 '22 18:09 matthewlein

Following up on this, errors raised during component rendering are caught at the frontloadServerRender catch block level, as you would expect, but errors that are raised in the async useFrontload function appear to not be.

matthewlein avatar Sep 14 '22 16:09 matthewlein