3

I'm building a React app and attempting to update some JavaScript functions to use ES6 destructured arrow syntax.

Index.js file:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

function TestMe() {
  const name = "User";
  const message = "Welcome!";
  return (
    <div>
      <Hello name={name} />
      <Message message={message} />
    </div>
  );
}

ReactDOM.render(<TestMe/>, document.querySelector('#root'));

const Hello = ({ name }) => (
    <span>Hello, {name}</span>
);

function Message(props) {
  return (
    <div className="message">
      {props.message}
    </div>
  );
}

The Message function will render, but the Hello function throws the following error in the browser (after successful build):

""" 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.

Check the render method of TestMe. """

Here's my package.json, just in case:

{
  "name": "jsx-exercises",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "eslint": "^5.6.0",
    "react": "^16.7.0",
    "react-dom": "^16.7.0",
    "react-scripts": "2.1.2"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "browserslist": [
    ">0.2%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ]
}

Why am I getting this error?

lane
  • 659
  • 8
  • 24

2 Answers2

1

Declarations in Javascript get "hoisted", which means that they can be accessed in the whole scope, even before they are declared. If you use a function declaration also the initialization happens when the scope starts:

 { // scope begins
   a();
   function a() { }
 } // scope ends

Now variables can only be accessed after they were initialized:

 setTimeout(() => console.log(a)); // 1
 console.log(a); // undefined
 var a = 1;

In your case you access Hello before it was initialized.


Fun fact: Accessing variables declared with let or const before the initialization happened throws a SyntaxError (for a good reason, q.e.d.) so one can see that your building pipeline replaced const with var to support older browsers.

Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
0

You must move Hello on the top of your file, because TestMe can't see this const. Functions javascript can see anyway, because it's function declaration

Vadim Hulevich
  • 1,803
  • 8
  • 17