Warning: input is a void element tag and must not have `children` or use `props.dangerouslySetInnerHTML`. Check the render method of null

vipin8169 picture vipin8169 · Mar 12, 2016 · Viewed 15.2k times · Source

I am trying to render the errors in the form if the ajax call to the form URL fails. Below is my Admin component:

#app/assets/javascripts/components/admin.js.coffee
@Admin = React.createClass
#  propTypes: ->
#    emailVal: React.PropTypes.string.isRequired

  getInitialState: ->
    edit: false
    errorTexts: []

  handleToggle: (e) ->
    e.preventDefault()
    @setState edit: [email protected]
    @setState errorTexts: []

  handleDelete: (e) ->
    e.preventDefault()
    # yeah... jQuery doesn't have a $.delete shortcut method
    $.ajax
      method: 'DELETE'
      url: "/admins/#{ @props.admin.id }"
      dataType: 'JSON'
      success: () =>
        @props.handleDeleteAdmin @props.admins

  handleEdit: (e) ->
    e.preventDefault()
    data = email: ReactDOM.findDOMNode(@refs.email).value
    # jQuery doesn't have a $.put shortcut method either
    $.ajax
      method: 'PUT'
      async: false
      url: "/admins/#{ @props.admin.id }"
      dataType: 'JSON'
      data:
        admin: data
      error: (data, status, xhr) =>
        errorTexts = []
        for key, value of data.responseJSON
          errorText = "#{key} #{value.toString()}"
          errorTexts.push errorText
        @replaceState errorTexts: errorTexts
        @setState edit: true
      success: (data, status, xhr) =>
        @setState edit: false
        @props.handleEditAdmin @props.admin, data

  adminRow: ->
    dom.tr null,
      dom.td null, @props.admin.email
      dom.td null,
        dom.a
          className: 'btn btn-default'
          onClick: @handleToggle
          'Edit'
        dom.a
          className: 'btn btn-danger'
          onClick: @handleDelete
          'Delete'

  adminForm: ->
    dom.tr null,
      dom.td null,
        dom.input
          className: 'form-control'
          type: 'text'
          defaultValue: @props.admin.email
          ref: 'email'
          for errorText, index in @state.errorTexts
            React.createElement AdminError, key: index, errorText: errorText
      dom.td null,
        dom.a
          className: 'btn btn-default'
          onClick: @handleEdit
          'Update'
        dom.a
          className: 'btn btn-danger'
          onClick: @handleToggle
          'Cancel'

  render: ->
    if @state.edit
      @adminForm()
    else
      @adminRow()

The corressponding AdminError component is:

#app/assets/javascripts/components/adminerror.js.coffee
@AdminError = React.createClass

  getDefaultProps: ->
    errorText: ""

  render: ->
    dom.div
      className: 'help-block'
      @props.errorText

While debugging I am getting the correct value of @props.errorText as "email is invalid". But it is not getting rendered on the page and I am geeting this warning in console: "Warning: input is a void element tag and must not have children or use props.dangerouslySetInnerHTML. Check the render method of null." Attached is the screenshot of both the error and the page. enter image description hereenter image description here

I tried changing the AdminError component as follows, but it didn't work:

#app/assets/javascripts/components/adminerror.js.coffee
@AdminError = React.createClass

  getDefaultProps: ->
    errorText: ""

  render: ->
    dom.div
      className: 'help-block'
      dangerouslySetInnerHTML: __html: marked(@props.errorText.toString(), {saitize: true})

When I set a debug point at the line returning dangerouslySetInnerHTML, I correctly get the value of @props.errorText as "email is invalid" and value of marked(@props.errorText.toString()) as "

email is invalid

".. but still the help-block for error is not rendered at all.

UPDATE: Made the following changes in the AdminError component

app/assets/javascripts/components/adminerror.js.coffee

@AdminError = React.createClass

  getDefaultProps: ->
#    errorText: ""
    errorTexts: []

  render: ->
    for errorText in @props.errorTexts
      dom.div
        className: 'help-block'
        errorText

and in the Admin component, made the following changes to the adminform method:

if(@state.errorTexts.length>0)
            dangerouslySetInnerHTML: {
              __html: ReactDOMServer.renderToString(
  #              for errorText, index in @state.errorTexts
                React.createElement AdminError, errorTexts: @state.errorTexts
              )
            }

not getting the warning anymore, but instead getting the following error:

Uncaught Invariant Violation: ReactCompositeComponent.render(): A valid ReactComponent must be returned. You may have returned undefined, an array or some other invalid object.

Answer

rmosolgo picture rmosolgo · Mar 14, 2016

Warning: input is a void element tag and must not have children ...

A dom.input may not have child elements.

But this code is trying to render error messages as children of a dom.input:

  dom.td null,
    dom.input
      className: 'form-control'
      type: 'text'
      defaultValue: @props.admin.email
      ref: 'email'
      # These are being rendered as children of the input: 
      for errorText, index in @state.errorTexts
        React.createElement AdminError, key: index, errorText: errorText

Can you render those error messages somewhere else? For example, as siblings of the input:

  dom.td null,
    dom.input
      className: 'form-control'
      type: 'text'
      defaultValue: @props.admin.email
      ref: 'email'
    for errorText, index in @state.errorTexts
      React.createElement AdminError, key: index, errorText: errorText