learner
learner

Reputation: 4808

Functions are not valid as a React child. This may happen if you return a Component instead of from render

I have written a Higher Order Component:

import React from 'react';


const NewHOC = (PassedComponent) => {
    return class extends React.Component {
        render(){
            return (
                <div>
                    <PassedComponent {...this.props}/>
                </div>
            )
        }
    }
}

export default NewHOC;

I am using the above in my App.js:

import React from 'react';
import Movie from './movie/Movie';
import MyHOC from './hoc/MyHOC';
import NewHOC from './hoc/NewHOC';
export default class App extends React.Component {
  render() {
   return (
    <div>
     Hello From React!!
     <NewHOC>
        <Movie name="Blade Runner"></Movie>
     </NewHOC>
    </div>
   );
  }
 }

But, the warning I am getting is:

Warning: Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> from render. Or maybe you meant to call this function rather than return it. in NewHOC (created by App) in div (created by App) in App

The Movie.js file is:

import React from "react";

export default class Movie extends React.Component{
    render() {
        return <div>
            Hello from Movie {this.props.name}
            {this.props.children}</div>
    }
}

What am I doing wrong?

Upvotes: 168

Views: 375910

Answers (15)

Joodi
Joodi

Reputation: 1

probably you forgot to add () after render function like this:

<div>
     {renderContent()}
</div>

Upvotes: 0

Chickenman
Chickenman

Reputation: 1670

I did encounter this error too because I didn't use the correct snytax at routing. This was in my App.js under the <Routes> section:

False:

<Route path="/movies/list" exact element={ MoviesList } />

Correct:

<Route path="/movies/list" exact element={ <MoviesList/> } />

So now the MoviesList is recognized as a component.

Upvotes: 149

Nirakar
Nirakar

Reputation: 1

You should use

const FunctionName = function (){
    return (
        `<div>
            hello world
        <div/>
    `
    )
};

if you use Es6 shorthand function it will give error use regular old javascript function.

Upvotes: 0

Rahul Shakya
Rahul Shakya

Reputation: 1425

In my case

<Link key={uuid()} to="#" className="tag">
  {post.department_name.toString}
</Link>

changed with

<Link key={uuid()} to="#" className="tag">
  {post.department_name.toString()}
</Link>

Upvotes: 0

ParisaN
ParisaN

Reputation: 2082

I had this error too. The problem was how to call the function.

Wrong Code:

const Component = () => {
    const id = ({match}) => <h2>Test1: {match.params.id}</h2>
    return <h1>{id}</h1>;
};

Whereas id is a function, So:

Correct code:

return <h1>{id()}</h1>;

Upvotes: 8

MichalPr
MichalPr

Reputation: 538

In my case I forgot to remove this part '() =>'. Stupid ctrl+c+v mistake.

const Account = () => ({ name }) => {

So it should be like this:

const Account = ({ name }) => {

Upvotes: 0

BL1133
BL1133

Reputation: 51

I encountered this error while following the instructions here: https://reactjs.org/docs/add-react-to-a-website.html

Here is what I had:

ReactDOM.render(Header, headerContainer);

It should be:

ReactDOM.render(React.createElement(Header), headerContainer);

Upvotes: 5

Sagiv b.g
Sagiv b.g

Reputation: 31014

You are using it as a regular component, but it's actually a function that returns a component.

Try doing something like this:

const NewComponent = NewHOC(Movie)

And you will use it like this:

<NewComponent someProp="someValue" />

Here is a running example:

const NewHOC = (PassedComponent) => {
  return class extends React.Component {
    render() {
      return (
        <div>
          <PassedComponent {...this.props} />
        </div>
      )
    }
  }
}

const Movie = ({name}) => <div>{name}</div>

const NewComponent = NewHOC(Movie);

function App() {
  return (
    <div>
      <NewComponent name="Kill Bill" />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"/>

So basically NewHOC is just a function that accepts a component and returns a new component that renders the component passed in. We usually use this pattern to enhance components and share logic or data.

You can read about HOCS in the docs and I also recommend reading about the difference between react elements and components

I wrote an article about the different ways and patterns of sharing logic in react.

Upvotes: 102

Joe Mwa
Joe Mwa

Reputation: 175

What would be wrong with doing;

<div className="" key={index}>
   {i.title}
</div>

[/*Use IIFE */]

{(function () {
     if (child.children && child.children.length !== 0) {
     let menu = createMenu(child.children);
     console.log("nested menu", menu);
     return menu;
   }
 })()}

Upvotes: 1

In my case, I was transport class component from parent and use it inside as a prop var, using typescript and Formik, and run well like this:

Parent 1

import Parent2 from './../components/Parent2/parent2'
import Parent3 from './../components/Parent3/parent3'

export default class Parent1 extends React.Component {
  render(){
    <React.Fragment>
      <Parent2 componentToFormik={Parent3} />
    </React.Fragment>
  }
}

Parent 2

export default class Parent2 extends React.Component{
  render(){
    const { componentToFormik } = this.props
    return(
    <Formik 
      render={(formikProps) => {
        return(
          <React.fragment>
            {(new componentToFormik(formikProps)).render()}
          </React.fragment>
        )
      }}
    />
    )
  }
}

Upvotes: 1

OZZIE
OZZIE

Reputation: 7338

I was getting this from webpack lazy loading like this

import Loader from 'some-loader-component';
const WishlistPageComponent = loadable(() => import(/* webpackChunkName: 'WishlistPage' */'../components/WishlistView/WishlistPage'), {
  fallback: Loader, // warning
});
render() {
    return <WishlistPageComponent />;
}


// changed to this then it's suddenly fine
const WishlistPageComponent = loadable(() => import(/* webpackChunkName: 'WishlistPage' */'../components/WishlistView/WishlistPage'), {
  fallback: '', // all good
});    

Upvotes: 1

greatgumz
greatgumz

Reputation: 418

I was able to resolve this by using my calling my high order component before exporting the class component. My problem was specifically using react-i18next and its withTranslation method, but here was the solution:

export default withTranslation()(Header);

And then I was able to call the class Component as originally I had hoped:

<Header someProp={someValue} />

Upvotes: 2

That&#39;s Enam
That&#39;s Enam

Reputation: 286

it also happens when you call a function from jsx directly rather than in an event. like

it will show the error if you write like

<h1>{this.myFunc}<h2>

it will go if you write:

<h1 onClick={this.myFunc}>Hit Me</h1>

Upvotes: 1

Stefan Michev
Stefan Michev

Reputation: 5093

In my case i forgot to add the () after the function name inside the render function of a react component

public render() {
       let ctrl = (
           <>
                <div className="aaa">
                    {this.renderView}
                </div>
            </>
       ); 

       return ctrl;
    };


    private renderView() : JSX.Element {
        // some html
    };

Changing the render method, as it states in the error message to

        <div className="aaa">
            {this.renderView()}
        </div>

fixed the problem

Upvotes: 35

Vishal Gupta
Vishal Gupta

Reputation: 208

Adding to sagiv's answer, we should create the parent component in such a way that it can consist all children components rather than returning the child components in the way you were trying to return.

Try to intentiate the parent component and pass the props inside it so that all children can use it like below

const NewComponent = NewHOC(Movie);

Here NewHOC is the parent component and all its child are going to use movie as props.

But any way, you guyd6 have solved a problem for new react developers as this might be a problem that can come too and here is where they can find the solution for that.

Upvotes: 3

Related Questions