4

I get the following error:

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

I also get this warning from React:

Warning: React.createElement: type should not be null, undefined, boolean, or number. It should be a string (for DOM elements) or a ReactClass (for composite components).

The actual problem I have faced (as I understood through debugging) is that I can't pass class as an argument, like this: <BigCard pokemon={result} />, because result here is an object of the class. What should I do to make it work correctly. Are there any best practices out there for passing classes as arguments?

I have this component:

export var BigCard = React.createClass({
  render: function() {
    var rows = [];
    var pokemon = this.props.pokemon;
    for (var variable in pokemon) {
      if (pokemon.hasOwnProperty(variable) && variable.toString() !== 'id' && variable.toString !== 'name' && variable.toString !== 'image' && variable.toString !== 'types') {
        rows.push(
          <tr>
            <td class='mdl-data-table__cell--non-numeric'>
              {variable}
            </td>
            <td>
              {pokemon[variable]}
            </td>
          </tr>
        )
      }
    }
    return (
      <div class='mdl-card mdl-shadow--4dp'>
        <div class='mdl-card__title'>
          <img src={pokemon.image.src} alt='Pokemon' class='bigCard__img'/>
        </div>
        <h2 class='mdl-card__title-text'></h2>
        <div class='mdl-card__supporting-text'>
          <table class='mdl-data-table mdl-js-data-table'>
            <thead>
              <tr>
                <th class='mdl-data-table__cell--non-numeric'>Type</th>
                <th class='mdl-data-table__cell--non-numeric'>{pokemon.types}</th>
              </tr>
            </thead>
            <tbody>
              {rows}
            </tbody>
          </table>
        </div>
      </div>
    );
  }
});

I have the following code, that I would like to run:

import React from 'react';
import ReactDOM from 'react-dom';
import * as DataLogic from './modules/data-logic.js';
import SmallCard from './components/SmallCard.jsx';
import BigCard from './components/BigCard.jsx';

DataLogic.getPokemonById(3).then((result) => {
  ReactDOM.render(
    <BigCard pokemon={result} />,
    document.getElementById('bigCard')
  );
}).catch((error) => console.log(`${error} in main.js`));

The result of getPokemonById is object of class DetailedPokemon. This is my class, which serves as a viewmodel:

export default class DetailedPokemon {
  constructor(id, name, image, types, attack, defense, hp, spAttack, spDefense, speed, weight, totalMoves) {
    this.id = id;
    this.name = name;
    this.image = image;
    this.types = types;
    this.attack = attack;
    this.defense = defense;
    this.hp = hp;
    this.spAttack = spAttack;
    this.spDefense = spDefense;
    this.speed = speed;
    this.weight = weight;
    this.totalMoves = totalMoves;
  }
}

I hope, I explained everything clearly. Can you help me with my problem please?

2
  • What's the error you are getting? JSON.parse is for parsing strings containing JSON. If result is an object then you should not pass it to JSON.parse. Commented Mar 28, 2016 at 21:39
  • @FelixKling thank you, I have edited the question! Commented Mar 28, 2016 at 21:55

2 Answers 2

3

You import BigCard incorrectly, perhaps SmallCard too.

When you export something with export foo = 'bar', foo is imported using curly brackets: import {foo} from './fooFile'.

If you want to import using import foo from ./fooFile, fooFile has to export a default: export default const BigCard = React.createClass(...

and that should take care of it.

Sign up to request clarification or add additional context in comments.

1 Comment

Here is more about difference in kinds of export: exploringjs.com/es6/ch_modules.html#_the-basics-of-es6-modules
2

This is likely from importing something the wrong way. I think this will work:

In your main app file:

import BigCard from './components/BigCard';

At the top, just assign a regular variable:

var BigCard = React.createClass({...})

And at the bottom of your BigCard component:

export default BigCard;

There are a few ways to do this, with ES6:


By extending React.Component:

export default class BigCard extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (<div>MyComponent</div>);
  }
}

Note the use of React.Component instead of React.createClass, they are almost the same. However with React.Component, componentWillMount logic is placed in the constructor. Along with a few other notable differences: https://toddmotto.com/react-create-class-versus-component/


With React.createClass:

const BigCard = React.createClass({
  render() {
    return (
      <div></div>
    );
  }
});

export default BigCard;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.