React createElement not working after upgrade to version 18.2

566 Views Asked by At

I am using React createElement in 5 components of my application. This was working fine when running react and react-dom version 17.0.2. I recently upgraded to version 18.2.0 and now I am getting the error message:

Warning: React.createElement: 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 is defined in, or you might have mixed up default and named imports. 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 is defined in, or you might have mixed up default and named imports.

at renderElement (C:\Users\jterr\Documents\NodeProjects\TeachLearnPlay\node_modules\react-dom\cjs\react-dom-server-legacy.node.development.js:6047:9) at renderNodeDestructiveImpl (C:\Users\jterr\Documents\NodeProjects\TeachLearnPlay\node_modules\react-dom\cjs\react-dom-server-legacy.node.development.js:6108:11)

There is more to the error message but I have omitted for brevity.

Note that the error message does not indicate any of my components to be an issue. It does reference Node modules.

This was a fresh install. I had removed the node_modules folder and the package-lock.json file prior to the npm install command.

I have seen all of the similar questions with this message and have checked and double checked that I am "exporting default" each of the components. I have tried placing the "export default" on the initial function definition and have also put it at the bottom of the component as it sits now.

I am using server side rendering.

Below is an example where I am using the createElement. Below that is the component that it is trying to create. Note that I have commented out other components that would normally be created so that I can focus on solving this without having to change multiple components.

//import React from "react";
//import DisplayAssociation from "./displayAssociation";
import DisplayDefinition from "./displayDefinition";
//import DisplayQuestionMultiChoice from "./displayQuestionMultiChoice";
//import DisplaySegment from "./displaySegment";
//import DisplayStatement from "./displayQuestionMultiChoice";

const Components =  {
  //Association: DisplayAssociation,
  Definition: DisplayDefinition,
  /*
  QuestionMultiChoice: DisplayQuestionMultiChoice,
  //Quote: DisplayQuote,
  //Prefix: DisplayPrefix,
  Segment: DisplaySegment,
  Statement: DisplayStatement,
  //Suffix: DisplaySuffix,
  */
};

export const DisplayConstructSwitch = ( block,
                                  finalDisplayConstructs, 
                                  setFinalDisplayConstructs,
                                  displayFramework,
                                  setDisplayFramework,
                                  okToChange,
                                  completed,
                                  numberCorrect,
                                  setNumberCorrect,
                                  numberWrong,
                                  setNumberWrong,
                                  totalAttempts,
                                  setTotalAttempts, ) => {

  // component does exist
  console.log("DisplayConstructSwitch - start block = ", block );
  console.log("DisplayConstructSwitch - start block.subType = ", block.subType );
  console.log("DisplayConstructSwitch - start typeof Components[block.subType] = ", typeof Components[block.subType] );
  if (typeof Components[block.subType] !== "undefined") {
    return React.createElement(Components[block.subType], {
                                                            key: block.constructId,
                                                            finalDisplayConstruct: block,
                                                            finalDisplayConstructs: finalDisplayConstructs,
                                                            setFinalDisplayConstructs: setFinalDisplayConstructs,
                                                            displayFramework: displayFramework,
                                                            setDisplayFramework: setDisplayFramework,
                                                            okToChange: okToChange,
                                                            completed: completed,
                                                            numberCorrect: numberCorrect,
                                                            setNumberCorrect: setNumberCorrect,
                                                            numberWrong: numberWrong,
                                                            setNumberWrong: setNumberWrong,
                                                            totalAttempts:totalAttempts,
                                                            setTotalAttempts: setTotalAttempts,
                                                          });
  }
  // component doesn't exist yet
  return React.createElement(
    () => <div>The component {block.constructResponseFormat} has not been created yet.</div>,
    { key: block.constructId }
  );
}

Here is the DisplayDefinition Component that should be created.

import React, { useState, useEffect } from "react";
import { makeStyles } from "@material-ui/core/styles";
import Paper from "@material-ui/core/Paper";

const useStyles = makeStyles((theme) => ({

  paper: {
    padding: theme.spacing(1),
    display: "flex",
    overflow: "auto",
    flexDirection: "column",
  },
}));

function DisplayDefinition(props) {
    const {displayConstruct} = props;
    const classes = useStyles();

  const wordToDefine = displayConstruct.constructDetail.wordToDefine;
  const wordDefinitions = displayConstruct.constructDetail.wordDefinitions;

  console.log("DisplayDefinition - wordToDefine = ", wordToDefine );
  console.log("DisplayDefinition - wordDefinitions = ", wordDefinitions );


  useEffect(() => {
    console.log("DisplayDefinition - in useEffect - wordToDefine = ", wordToDefine );

  }, [wordToDefine]);

    return (
        <>
        <Paper className={classes.paper} elevation={3}>
        <label>
            Word to Define:  {wordToDefine}
        </label>
        <label>
            Definition:  {wordDefinitions[0]}
        </label>
        </Paper>
        </>
    )
}

export default DisplayDefinition;

The only code changes in these components between the versions was to comment out extra components while I trouble shoot.

Can anyone see any issue with what I have done that would have allowed version 17 to work but not version 18?

Can it be that this code is fine but there is some other change that I need to make and it is manifesting itself as a false createElement issue? If so, what might that be?

0

There are 0 best solutions below