Error when trying to set up Tina for first time - Cannot read property 'all' of undefined

I’m getting the following error when trying to set up TinaCMS on a next.js website.

Cannot read property 'all' of undefined
TypeError: Cannot read property 'all' of undefined
    at n.Alerts (C:\Development\TorqIT\TorqIT-next\node_modules\@tinacms\react-alerts\build\index.js:1:5729)
    at processChild (C:\Development\TorqIT\TorqIT-next\node_modules\react-dom\cjs\react-dom-server.node.development.js:3043:14)
    at resolve (C:\Development\TorqIT\TorqIT-next\node_modules\react-dom\cjs\react-dom-server.node.development.js:2960:5)
    at ReactDOMServerRenderer.render (C:\Development\TorqIT\TorqIT-next\node_modules\react-dom\cjs\react-dom-server.node.development.js:3435:22)
    at ReactDOMServerRenderer.read (C:\Development\TorqIT\TorqIT-next\node_modules\react-dom\cjs\react-dom-server.node.development.js:3373:29)
    at renderToString (C:\Development\TorqIT\TorqIT-next\node_modules\react-dom\cjs\react-dom-server.node.development.js:3988:27)
    at render (C:\Development\TorqIT\TorqIT-next\node_modules\next\dist\next-server\server\render.js:83:16)
    at Object.renderPage (C:\Development\TorqIT\TorqIT-next\node_modules\next\dist\next-server\server\render.js:419:16)
    at Function.getInitialProps (C:\Development\TorqIT\TorqIT-next\.next\server\static\development\pages\_document.js:293:19)
    at Object.loadGetInitialProps (C:\Development\TorqIT\TorqIT-next\node_modules\next\dist\next-server\lib\utils.js:59:29)
    at Object.renderToHTML (C:\Development\TorqIT\TorqIT-next\node_modules\next\dist\next-server\server\render.js:423:36)
    at async DevServer.renderToHTMLWithComponents (C:\Development\TorqIT\TorqIT-next\node_modules\next\dist\next-server\server\next-server.js:652:26)
    at async DevServer.renderToHTML (C:\Development\TorqIT\TorqIT-next\node_modules\next\dist\next-server\server\next-server.js:799:28)
    at async DevServer.renderToHTML (C:\Development\TorqIT\TorqIT-next\node_modules\next\dist\server\next-dev-server.js:19:539)
    at async DevServer.render (C:\Development\TorqIT\TorqIT-next\node_modules\next\dist\next-server\server\next-server.js:541:22)
    at async Object.fn (C:\Development\TorqIT\TorqIT-next\node_modules\next\dist\server\next-dev-server.js:9:383)

Can you post the code that instantiates the TinaCMS object?

We don’t use a Class based nextjs App so this is my first pass at getting it working with a funcional _app.js

const MyApp = ({ Component, pageProps }) => {
  useEffect(() => {
    // unrelated stuff
  }, []);

  const [tina] = useState(new initializeTina());

  return (
    <TinaProvider cms={tina}>
      <Component {...pageProps} />
    </TinaProvider>
  );
};

function initializeTina() {
  const tina = new TinaCMS();
  const client = new GitClient("http://localhost:3000/___tina");
  tina.registerApi("git", client);
  tina.media.store = new GitMediaStore(client);
}

export default MyApp;

I think that’s setting tina as an empty object {}. Try changing to:

const MyApp = ({ Component, pageProps }) => {
  useEffect(() => {
    // unrelated stuff
  }, []);

-  const [tina] = useState(new initializeTina());
+  const [tina] = useState(initializeTina());

  return (
    <TinaProvider cms={tina}>
      <Component {...pageProps} />
    </TinaProvider>
  );
};

function initializeTina() {
  const tina = new TinaCMS();
  const client = new GitClient("http://localhost:3000/___tina");
  tina.registerApi("git", client);
  tina.media.store = new GitMediaStore(client);
+ return tina
}

export default MyApp;

:man_facepalming:

I missed that when extracting the new call into the method.

And since {} isn’t falsy, I assume it bypasses any basic sanity checks the code does for not being passed a TinaCMS object.

Yeah, maybe a more explicit check would be good:

if (!(cms instanceof CMS)) {
  throw new Error('This is not a CMS')
}

Feel like contributing? :stuck_out_tongue:

Any tips for testing? I’m trying to use npm link either at the root of the tina repo or in the root of the tinacms package folder and getting the following error:

Server Error
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.

This error happened while generating the page. Any console logs will be displayed in the terminal window.
Call Stack
resolveDispatcher
file:///C:/Development/Tools/tinacms/node_modules/react/cjs/react.development.js (1590:13)
Object.useState
file:///C:/Development/Tools/tinacms/node_modules/react/cjs/react.development.js (1618:20)
...

Yeah since react and styled-components have runtimes using NPM link is not an option.

For that reason we created a @tinacms/webpack-helpers package that lets you use webpack aliases. it only works for the frontend code that’s loaded via webpack.

In the tinacms.org repo we setup our next config to make it easy to turn this on and off.

I managed to run a test via @testing-library/react and confirmed that the TypeError actually throws before the code actually runs.

Testing this:

export const TinaProvider: React.FC<TinaProviderProps> = ({
  cms,
  children,
  hidden,
  position,
  styled = true,
}) => {
  throw new Error('Testing Error')

  // Won't be hit because of above testing error
  if (!(cms instanceof CMS)) {
    throw new Error('prop cms is not an instance of CMS')
  }

  return (
    <CMSContext.Provider value={cms}>
      <ModalProvider>
        {cms.enabled && styled && <Theme />}
        <Alerts alerts={cms.alerts} />
        <ToolbarProvider hidden={hidden} toolbar={cms.toolbar} />
        <SidebarProvider
          hidden={hidden}
          position={position}
          sidebar={cms.sidebar}
        >
          {children}
        </SidebarProvider>
      </ModalProvider>
    </CMSContext.Provider>
  )
}

It throws the same TyepError: cannot read property 'all' of undefined error before even hitting my throw call.

How can cms being an empty object cause an error when it hasn’t even been passed to the child provider component yet?

I did determine that if I’m using _app.tsx instead of _app.js the typescript checks actually run and highlight the mistake with the original code being incorrect.

This makes no sense to me :confused:

Me either :ok_man:

Here’s my test and branch if you want to look again. I’m not going to make a PR with a fix that doesn’t actually fix it.

Meh, make a PR I’ll merge it into a new branch and see if the CI works from there

PR up here: https://github.com/tinacms/tinacms/pull/1196

1 Like