[useQuerySubscription] TypeError: Cannot read property 'enabled' of undefined

Do you know why I am getting this error in terminal?

TypeError: Cannot read property 'enabled' of undefined
    at useQuerySubscription (/Users/primozrome/Documents/Web/gostinskaoprema/node_modules/react-datocms/dist/cjs/useQuerySubscription/index.js:66:27)
    at Layout (webpack-internal:///./components/layout/Layout.js:17:111)
    at processChild (/Users/primozrome/Documents/Web/gostinskaoprema/node_modules/react-dom/cjs/react-dom-server.node.development.js:3353:14)
    at resolve (/Users/primozrome/Documents/Web/gostinskaoprema/node_modules/react-dom/cjs/react-dom-server.node.development.js:3270:5)
    at ReactDOMServerRenderer.render (/Users/primozrome/Documents/Web/gostinskaoprema/node_modules/react-dom/cjs/react-dom-server.node.development.js:3753:22)
    at ReactDOMServerRenderer.read (/Users/primozrome/Documents/Web/gostinskaoprema/node_modules/react-dom/cjs/react-dom-server.node.development.js:3690:29)
    at Object.renderToString (/Users/primozrome/Documents/Web/gostinskaoprema/node_modules/react-dom/cjs/react-dom-server.node.development.js:4298:27)
    at renderPage (/Users/primozrome/Documents/Web/gostinskaoprema/node_modules/next/dist/server/render.js:723:46)
    at Object.ctx.renderPage (webpack-internal:///./pages/_document.js:25:30)
    at Object.defaultGetInitialProps (/Users/primozrome/Documents/Web/gostinskaoprema/node_modules/next/dist/server/render.js:364:51)

It is raised in my Layout component, but it doesn’t affect page render. Just get an error in Terminal:

import { Box } from "@chakra-ui/react";
import Header from "./Header";
import { useQuerySubscription } from "react-datocms";

export default function Layout({ children }) {
  const {
    data: { allMenuMains },
  } = useQuerySubscription(children.props.subscription);
  return (
    <Box>
      <Header menuItems={allMenuMains} />
      <Box as="main">{children}</Box>
      <footer>Footer</footer>
    </Box>
  );
};

Hello @primoz.rome
Could you console.log(children.props.subscription) before the first const declaration on your Layout component and send us the output?

Thanks!

@m.finamor I just did that, here is the output:

$ next dev
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
info  - Loaded env from /Users/primozrome/Documents/Web/gostinskaoprema/.env
event - compiled client and server successfully in 4.5s (711 modules)
wait  - compiling / (client and server)...
event - compiled client and server successfully in 845 ms (718 modules)
{
  enabled: false,
  initialData: {
    allMenuMains: [
      [Object], [Object],
      [Object], [Object],
      [Object], [Object],
      [Object]
    ]
  }
}
wait  - compiling /_error (client and server)...
event - compiled client and server successfully in 970 ms (719 modules)
undefined
TypeError: Cannot read property 'enabled' of undefined
    at useQuerySubscription (/Users/primozrome/Documents/Web/gostinskaoprema/node_modules/react-datocms/dist/cjs/useQuerySubscription/index.js:66:27)
    at Layout (webpack-internal:///./components/layout/Layout.js:18:111)
    at processChild (/Users/primozrome/Documents/Web/gostinskaoprema/node_modules/react-dom/cjs/react-dom-server.node.development.js:3353:14)
    at resolve (/Users/primozrome/Documents/Web/gostinskaoprema/node_modules/react-dom/cjs/react-dom-server.node.development.js:3270:5)
    at ReactDOMServerRenderer.render (/Users/primozrome/Documents/Web/gostinskaoprema/node_modules/react-dom/cjs/react-dom-server.node.development.js:3753:22)
    at ReactDOMServerRenderer.read (/Users/primozrome/Documents/Web/gostinskaoprema/node_modules/react-dom/cjs/react-dom-server.node.development.js:3690:29)
    at Object.renderToString (/Users/primozrome/Documents/Web/gostinskaoprema/node_modules/react-dom/cjs/react-dom-server.node.development.js:4298:27)
    at renderPage (/Users/primozrome/Documents/Web/gostinskaoprema/node_modules/next/dist/server/render.js:723:46)
    at Object.ctx.renderPage (webpack-internal:///./pages/_document.js:25:30)
    at Object.defaultGetInitialProps (/Users/primozrome/Documents/Web/gostinskaoprema/node_modules/next/dist/server/render.js:364:51)

It seems like the first time that component is called, it is able to get the children.props, and can then create the subscription accordingly.
However, on the second call for your Layout component, as you can see in the quote block above, it can’t access the children prop (undefined) and therefore can’t read the “enabled” property of something it can’t access.
A quick fix, if you are getting the desired behaviour already from that subscription, would be to wrap it around an if, to make sure it only tries to create the subscription, if it has access to the children props:
So something like:

import { Box } from "@chakra-ui/react";
import Header from "./Header";
import { useQuerySubscription } from "react-datocms";

export default function Layout({ children }) {
  if(children.props.subscription){
    const {
      data: { allMenuMains },
    } = useQuerySubscription(children.props.subscription);
  }
  return (
    <Box>
      <Header menuItems={allMenuMains} />
      <Box as="main">{children}</Box>
      <footer>Footer</footer>
    </Box>
  );
};

Would solve your problem

@m.finamor

Ok I tried that, but I get an exception that allMenuMains prop is not defined… I could go on and solve this with some additional workarounds, but it just doesn’t feel like a clean solution. The firs question is why this is called two times and the subscription first is available, but then not?

@primoz.rome

The component seems to be called twice because it’s props are updated, and react re-renders a component every time it’s props are updated.

And on why the subscription doesn’t work, it is because when the props update on your component, they go from receiving the correct props, to receiving undefined (as we saw in the console.log) and you end up passing the equivalent of useQuerySubscription(undefined) and this will always fail, as that function tries to read the property “enabled” to the object passed to it, and will generate an error if that property doesn’t exist.

So the root of the problem here is the prop management on this component, that goes from receiving the right object, to being updated (and re-rendered because of this update) to undefined, causing the subscription to fail.

1 Like

@m.finamor is this if(children.props.subscription) some sort of standard hack when using live preview for this subscription, or is isolated case to my project?

Still trying to solve this properly.

@primoz.rome this is an isolated case to your project, as it is strictly related to how you pass the argument to our library function.

The only way to go around it would be to see how you are passing props to your components on your project, as it seems that the Subscription prop has the appropriate value on the first call to the component, but not when it is re-evaluated, as it is undefined

If you want, you can share the git repo of the project with us at support@datocms.com so we can take a better look and find out the exact source of the problem :slight_smile: