HOC: A valid React element (or null) must be returned

773 views Asked by At

I am trying to create HOC to wrap modals in, and am getting this error: A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.

I have checked the few other threads, and the issues mainly seem to be imports - however I do not believe that is the case here. Here is my code:

create-modal.js

import { Component } from 'react'
import withRedux from 'next-redux-wrapper'
import Layout from '../../components/layouts/main'
import ModalContainer from './modal-container'

// Modal Layouts
import Empty from './empty'
import Basic from './basic'

const data = {
  title: 'Silly Modal.',
  layout: 'empty',
  customClass: '',
  multiStep: false,
  steps: [
    {
      isVisible: true,
      isAnimated: false,
      animationName: null,
      header: 'TEST',
      currentContent: 'Testing the modal. What fun!',
      buttons: {
        closeText: 'Close',
        closeAction: null,
        continueText: null,
        continueAction: null,
      },
      closeRedirect: null,
      closeRedirectPath: null,
      continueRedirect: null,
      continueRedirectPath: null,
    },
  ],
}

function newModal (WrappedComponent, data) {
  if (!WrappedComponent && !data) return null

  return class Modal extends Component {
    constructor (props) {
      super(props)
    }
    render () {
      return (
        <Layout>
          <ModalContainer>
            <WrappedComponent />
          </ModalContainer>
        </Layout>
      )
    }
  }
}

console.log('what is newModal returning?!', (newModal(<Basic />, data)) )

export default newModal

console.logging the return of calling this HOC shows that it is returning a function rather than a component:

function Modal(props) { (0, _classCallCheck3.default)(this, Modal); return (0, _possibleConstructorReturn3.default)(this, (Modal.__proto__ || (0, _getPrototypeOf2.default)(Modal)).call(this, props…

Which seems wrong.

I should also note that I may be doing this return wrong (but am not sure. I have tried return <WrappedComponent /> with the same result however :(

All of the components I am importing are exported as default so not using the brackets on the import is, I believe, correct here. I am new to HOC's and am just not seeing what is wrong, as I am following the patterns I see for them closely. Any help is appreciated!

3

There are 3 answers

4
Mikkel On

You are returning the class constructor with this statement:

return class Modal extends Component {

which is why it's complaining

You could probably just use a pure React component, as you appear not to be needing props or state.

That will get you past this problem, but I suspect you need to do it differently anyway, because it looks like you want to pass in an element, and render that element inside a modal wrapper.

Look up how to use {this.props.children} for a clue, or if I'm on the right track I can help you more.

UPDATE

I think what you want to do is take advantage of children. You can do something like this:

<ModalWrapper name="A modal dialog (which is generic and re-usable)">
  <SomethingElse name="This is my custom component">
     :
     :
  </SomethingElse>
</ModalWrapper>

In the render method of ModalWrapper you just render {this.props.children} and it brings in whatever markup you have as children.

(I am not 100% sure if it's {this.props.children}, but you'll get my drift

1
elmasse On

An HOC is a function that receives a Component, wraps it to add more functionality and return another component. It is not that you can use it as a Component in your code. You use it to enhance an existing Component.

0
Tal Joffe On

You are not using the HOC component correctly, you should do it like this:

import Basic from './basic'
...
const NewModal = newModal(Basic, data)
...
render()
<NewModal ... />

Look at the official react documentation for an example: https://reactjs.org/docs/higher-order-components.html