0

I am calling a general component called cmsBlock in Magento PWA. I can't really do many changes to that component as it is used in many pages. However on my CartPage I want to render null if the CMS-block throws error ( i e the CMS block is disabled and the identifier cannot be found).

The problem is that in cmsBlock.js an error actually renders something ( I can add a className, but that is basically all I am allowed do to that component, so no ErrorBoundary can be used on csmBlock) so I cannot check for null or undefined:

 const { loading, error, data } = useQuery(GET_CMS_BLOCKS, {
    variables: { identifiers }
});

if (loading) {
    return fullPageLoadingIndicator;
}

if (error) {
    return <div>Data Fetch Error</div>;
}

So that means I always get true when calling CMS-blocks. In my Cart page I have tried this (cartPage.js):

const cmsBlock = <CmsBlock identifiers={'cartpage-block'} />;

const cmsBlockHolder =
    cmsBlock ? (
        <div className={classes.cmsblock}>              
        </div>
    ) : null;

But I need to add an additional condition to check if the cmsBlock component return error, because then I should not allow to render the cmsBlockHolder at all. Any ideas on how to solve this without changing the cmsBlock.js?

Tess
  • 53
  • 1
  • 13

1 Answers1

0

This sounds like you look for Error Boundaries. Quoting the react docs:

Error boundaries work like a JavaScript catch {} block, but for components

What you have to do is define a new component which includes the lifecycle method getDerivedStateFromError(). There you can render a fallback UI if a child component throws an error. It could look like this for your use case:

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    // Update state so the next render will show the fallback UI.
    return { hasError: true };
  }

  render() {
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return null;
    }
    return this.props.children;
  }
}

And your component composition would look like this:

<ErrorBoundary>
  <CmsBlock />
</ErrorBoundary>
Gh05d
  • 7,923
  • 7
  • 33
  • 64
  • I tried that in CartPage already (which didn't work), I am not allowed to that in cmsBlock-component – Tess Jan 26 '21 at 13:53
  • But this is outside the CMS component. So you do not edit that one. Ok, if that does not work, have you thought about adding a ref and check whether the child has a specific class or maybe do this via document.getElementByClassName? – Gh05d Jan 26 '21 at 13:57
  • But will that work as it is client rendered? The user will not be happy if the CMSBlock background flashs by and then disappear. – Tess Jan 26 '21 at 13:58
  • Hm, good question. Unfortunately, I can't really answer that. Sorry. – Gh05d Jan 26 '21 at 14:04
  • The problem with your solution is that is has to be applied to cmsBlock in order to work properly. And I may not change that file – Tess Jan 26 '21 at 14:43