skip to Main Content

Error: Uncaught [Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.

Learning react from https://www.udemy.com/course/react-the-complete-guide-incl-redux

Section 8: Working with refs & portals

Instructions:

Exposing Component APIs

Your working on a part of an application that contains a form which should be resettable from outside that form.

A colleague prepared a Form component that contains a couple of dummy inputs and a "Save" button that’s not doing anything.

Your task is to expose a clear() function from inside that Form component so that other components that use the Form component can call that function to reset the form.

Because that exposed clear() function should call the form’s built-in reset() method (the JS form object, which is the underlying object of the <form> element, has a reset() method that does exactly what its name implies).

So the Form component should be usable like this:

function SomeComponent() {  const form = React.useRef();   function handleClear() {    form.current.clear();  }   return <Form ref={form}/>}

After adding this feature to the Form component you should tweak the App component to establish a "connection" to the Form component and call the newly exposed clear() method from inside the App component’s handleRestart() function.

So you should add code similar to the above code snippet to the App component.

Important: In this Udemy exercise workspace, any React Hooks (and other React functions!) must be accessed directly on the imported React object (import React from 'react') – for example: React.useState().

-- App.js

import React from 'react';
import Form from './Form';

// Don't change the name of the 'App' 
// function and keep it a named export

export default function App() {
  const formRef = React.useRef();

  function handleRestart() {
    formRef.current.clear();
  }

  return (
    <div id="app">
      <button onClick={handleRestart}>Restart</button>
      <Form ref={formRef} />
    </div>
  );
}
-- Form.js

import React from 'react';

const FormComponent = React.forwardRef((props, ref) => {
  const formRef = React.useRef();

  React.useImperativeHandle(ref, () => ({
    clear() {
      formRef.current.reset();
    }
  }), []);

  return (
    <form ref={formRef}>
      <p>
        <label>Name</label>
        <input type="text" />
      </p>

      <p>
        <label>Email</label>
        <input type="email" />
      </p>
      <p id="actions">
        <button type="button">Save</button> {/* Added type="button" to prevent form submission */}
      </p>
    </form>
  );
});

export default FormComponent;

-- index.css

@import url('https://fonts.googleapis.com/css2?family=Raleway:wght@400;700&family=Lato:wght@400;700&display=swap');

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: 'Raleway', sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  background: linear-gradient(#180d27, #0c0219);
  color: #e5d9f1;
  min-height: 100vh;
}

#app {
  margin: 2rem auto;
  padding: 1rem;
  max-width: 30rem;
  text-align: center;
  border-radius: 6px;
  background: linear-gradient(#341a89, #3a1967);
  box-shadow: 0 0 8px rgba(0, 0, 0, 0.3);
}

button {
  font-family: 'Lato', sans-serif;
  font-size: 1rem;
  font-weight: 700;
  padding: 0.5rem 1rem;
  border: 1px solid white;
  border-radius: 6px;
  background: none;
  color: #e5d9f1;
  cursor: pointer;
  transition: all 0.2s ease-in-out;
}

form button {
  background: linear-gradient(#9e21c8, #8b179c);
  border: none;
}

form {
  width: 90%;
  max-width: 40rem;
  margin: 3rem auto;
}

form label {
  display: block;
  margin-bottom: 0.5rem;
  font-size: 0.8rem;
  text-align: left;
  text-transform: uppercase;
  font-weight: bold;
  letter-spacing: 0.1rem;
}

form input {
  width: 100%;
  padding: 0.5rem;
  border: 1px solid #e5d9f1;
  border-radius: 6px;
  background: none;
  color: #e5d9f1;
  font-size: 1rem;
  font-family: 'Lato', sans-serif;
  margin-bottom: 1rem;
}

#actions {
  text-align: right;
}

It’s working when I try from local setup but fails udemy test cases with below errors –

Warning: React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Error: Uncaught [Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.]
    at reportException (/eval/node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:66:24)
    at innerInvokeEventListeners (/eval/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:353:9)
    at invokeEventListeners (/eval/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:286:3)
    at HTMLUnknownElementImpl._dispatch (/eval/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:233:9)
    at HTMLUnknownElementImpl.dispatchEvent (/eval/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:104:17)
    at HTMLUnknownElement.dispatchEvent (/eval/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:241:34)
    at Object.invokeGuardedCallbackDev (/eval/node_modules/react-dom/cjs/react-dom.development.js:4213:16)
    at invokeGuardedCallback (/eval/node_modules/react-dom/cjs/react-dom.development.js:4277:31)
    at beginWork$1 (/eval/node_modules/react-dom/cjs/react-dom.development.js:27451:7)
    at performUnitOfWork (/eval/node_modules/react-dom/cjs/react-dom.development.js:26560:12)
    at workLoopSync (/eval/node_modules/react-dom/cjs/react-dom.development.js:26466:5)
    at renderRootSync (/eval/node_modules/react-dom/cjs/react-dom.development.js:26434:7)
    at performConcurrentWorkOnRoot (/eval/node_modules/react-dom/cjs/react-dom.development.js:25738:74)
    at flushActQueue (/eval/node_modules/react/cjs/react.development.js:2667:24)
    at act (/eval/node_modules/react/cjs/react.development.js:2582:11)
    at /eval/node_modules/@testing-library/react/dist/act-compat.js:63:25
    at renderRoot (/eval/node_modules/@testing-library/react/dist/pure.js:159:26)
    at render (/eval/node_modules/@testing-library/react/dist/pure.js:246:10)
    at Object.<anonymous> (/eval/test/App.spec.js:30:11)
    at Promise.then.completed (/eval/node_modules/jest-circus/build/utils.js:298:28)
    at new Promise (<anonymous>)
    at callAsyncCircusFn (/eval/node_modules/jest-circus/build/utils.js:231:10)
    at _callCircusTest (/eval/node_modules/jest-circus/build/run.js:316:40)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
    at _runTest (/eval/node_modules/jest-circus/build/run.js:252:3)
    at _runTestsForDescribeBlock (/eval/node_modules/jest-circus/build/run.js:126:9)
    at _runTestsForDescribeBlock (/eval/node_modules/jest-circus/build/run.js:121:9)
    at run (/eval/node_modules/jest-circus/build/run.js:71:3)
    at runAndTransformResultsToJestFormat (/eval/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)
    at jestAdapter (/eval/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)
    at runTestInternal (/eval/node_modules/jest-runner/build/runTest.js:367:16)
    at runTest (/eval/node_modules/jest-runner/build/runTest.js:444:34) {
  detail: Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
      at createFiberFromTypeAndProps (/eval/node_modules/react-dom/cjs/react-dom.development.js:28439:17)
      at createFiberFromElement (/eval/node_modules/react-dom/cjs/react-dom.development.js:28465:15)
      at reconcileSingleElement (/eval/node_modules/react-dom/cjs/react-dom.development.js:15750:23)
      at reconcileChildFibers (/eval/node_modules/react-dom/cjs/react-dom.development.js:15808:35)
      at reconcileChildren (/eval/node_modules/react-dom/cjs/react-dom.development.js:19174:28)
      at updateHostRoot (/eval/node_modules/react-dom/cjs/react-dom.development.js:19883:5)
      at beginWork (/eval/node_modules/react-dom/cjs/react-dom.development.js:21615:14)
      at HTMLUnknownElement.callCallback (/eval/node_modules/react-dom/cjs/react-dom.development.js:4164:14)
      at HTMLUnknownElement.callTheUserObjectsOperation (/eval/node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30)
      at innerInvokeEventListeners (/eval/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:350:25)
      at invokeEventListeners (/eval/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:286:3)
      at HTMLUnknownElementImpl._dispatch (/eval/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:233:9)
      at HTMLUnknownElementImpl.dispatchEvent (/eval/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:104:17)
      at HTMLUnknownElement.dispatchEvent (/eval/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:241:34)
      at Object.invokeGuardedCallbackDev (/eval/node_modules/react-dom/cjs/react-dom.development.js:4213:16)
      at invokeGuardedCallback (/eval/node_modules/react-dom/cjs/react-dom.development.js:4277:31)
      at beginWork$1 (/eval/node_modules/react-dom/cjs/react-dom.development.js:27451:7)
      at performUnitOfWork (/eval/node_modules/react-dom/cjs/react-dom.development.js:26560:12)
      at workLoopSync (/eval/node_modules/react-dom/cjs/react-dom.development.js:26466:5)
      at renderRootSync (/eval/node_modules/react-dom/cjs/react-dom.development.js:26434:7)
      at performConcurrentWorkOnRoot (/eval/node_modules/react-dom/cjs/react-dom.development.js:25738:74)
      at flushActQueue (/eval/node_modules/react/cjs/react.development.js:2667:24)
      at act (/eval/node_modules/react/cjs/react.development.js:2582:11)
      at /eval/node_modules/@testing-library/react/dist/act-compat.js:63:25
      at renderRoot (/eval/node_modules/@testing-library/react/dist/pure.js:159:26)
      at render (/eval/node_modules/@testing-library/react/dist/pure.js:246:10)
      at Object.<anonymous> (/eval/test/App.spec.js:30:11)
      at Promise.then.completed (/eval/node_modules/jest-circus/build/utils.js:298:28)
      at new Promise (<anonymous>)
      at callAsyncCircusFn (/eval/node_modules/jest-circus/build/utils.js:231:10)
      at _callCircusTest (/eval/node_modules/jest-circus/build/run.js:316:40)
      at processTicksAndRejections (node:internal/process/task_queues:95:5)
      at _runTest (/eval/node_modules/jest-circus/build/run.js:252:3)
      at _runTestsForDescribeBlock (/eval/node_modules/jest-circus/build/run.js:126:9)
      at _runTestsForDescribeBlock (/eval/node_modules/jest-circus/build/run.js:121:9)
      at run (/eval/node_modules/jest-circus/build/run.js:71:3)
      at runAndTransformResultsToJestFormat (/eval/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)
      at jestAdapter (/eval/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)
      at runTestInternal (/eval/node_modules/jest-runner/build/runTest.js:367:16)
      at runTest (/eval/node_modules/jest-runner/build/runTest.js:444:34),
  type: 'unhandled exception'
}
Coding Exercise

udemy error

2

Answers


  1. Chosen as BEST ANSWER

    I invested a lot of time in this exercise comparing the given answer with my code. At the end, I found that removing the default property in the export of App() fixed the issue (i.e. simply do export function App(){...}instead of export default function App(){...}).

    enter image description here


  2. At the beginning, you imported forwardRef from react. to use it in you component. then you exporting a function called forwardRef that returning a jsx form. the issue is you should’t name component the same as the function you’re wrapping with forwardRef. so change your component something like this :

    const YourComponentName = forwardRef((props, ref) => {
        const formRef = React.useRef();
    
        // rest of the functions
       
        return (
            // Your jsx content...
        );
    });
    

    YourComponentName Change this to your component name that cannot be the name forwardRef

    Thanks!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search