Danny Dyer Danny Dyer - 1 month ago 15
React JSX Question

React - A valid React element (or null) must be returned

I have the following React component:

import React, {Component} from 'react';
import $ from 'jquery';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';

class SamplesInnerLrg extends Component {
playSample (refName,event) {
var idClicked = this.refs[refName];
var linkAudio = $(idClicked).children("#myAudio")[0];
linkAudio.play();
}
render() {
return this.props.samples.map((sample) => {
return (
<div key={sample.id} className="sample-comp-lge">
<div className="sample-comp-lge-header">
<span className="sample-comp-lge-Name">{sample.sampleName}</span>
<span className="sample-comp-lge-id">{sample.sampleFamily}</span>
</div>
<div className="sample-comp-lge-audio" ref={sample.id} onClick={this.playSample.bind(this,sample.id)}>
<audio preload="auto" id="myAudio">
<source src={sample.soundSource} type="audio/wav" />
</audio>
</div>
<div className="sample-comp-lge-owner">{sample.uploader}</div>
</div>
)
})
}
}

function mapStateToProps(state) {
return {
samples:state.samples
};
}

export default connect(mapStateToProps)(SamplesInnerLrg);


The issue here is i'm getting the error "A valid React element (or null) must be returned ". After looking at a few similar issues on here it looks like the usual issue is not wrapping the JSX in a parent non parallel element. In my code above it is wrapped with the parent so not sure why I am getting the error.

Worth mentioning the error says the problematic component is Invariant Violation: SamplesInnerLrg.render()

New to React so appreciate all the help I can get

Answer

React should return a single HTML node. In your case, you're returning an array of nodes.

Try this:

 return <div>
   {
     this.props.samples.map((sample) => {
        return (
                <div key={sample.id} className="sample-comp-lge">
                    <div className="sample-comp-lge-header">
                        <span className="sample-comp-lge-Name">{sample.sampleName}</span>
                        <span className="sample-comp-lge-id">{sample.sampleFamily}</span>
                    </div>
                    <div className="sample-comp-lge-audio" ref={sample.id} onClick={this.playSample.bind(this,sample.id)}>
                        <audio preload="auto" id="myAudio">
                              <source src={sample.soundSource} type="audio/wav" />
                        </audio>
                    </div>
                    <div className="sample-comp-lge-owner">{sample.uploader}</div>
                </div>
            )
        })
     }
   </div>

By doing this, you're wrapping the array of nodes under a <div> node.