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?