How do I fix "Expected to return a value at the end of arrow function" warning?

JavascriptReactjsEcmascript 6ReduxReact Redux

Javascript Problem Overview


Everything works fine, but I have this warning Expected to return a value at the end of arrow function array-callback-return. I tried using forEach instead of map, but then <CommentItem /> doesn't even show. How do I fix this?

  return this.props.comments.map((comment) => {
  
      if (comment.hasComments === true) {
      
        return (
          <div key={comment.id}>
          
            <CommentItem className="MainComment"/>

              {this.props.comments.map(commentReply => {
              
                if (commentReply.replyTo === comment.id) { 
                  return (
                    <CommentItem className="SubComment"/>
                 ) // return
                } // if-statement
              }) // map-function
              } // map-function __begin
            
          </div> // comment.id
          
        ) // return

Javascript Solutions


Solution 1 - Javascript

A map() creates an array, so a return is expected for all code paths (if/elses).

If you don't want an array or to return data, use forEach instead.

Solution 2 - Javascript

The warning indicates that you're not returning something at the end of your map arrow function in every case.

A better approach to what you're trying to accomplish is first using a .filter and then a .map, like this:

this.props.comments
  .filter(commentReply => commentReply.replyTo === comment.id)
  .map((commentReply, idx) => <CommentItem key={idx} className="SubComment"/>);

Solution 3 - Javascript

The easiest way only if you don't need return something it'ts just return null

Solution 4 - Javascript

The problem seems to be that you are not returning something in the event that your first if-case is false.

The error you are getting states that your arrow function (comment) => { doesn't have a return statement. While it does for when your if-case is true, it does not return anything for when it's false.

return this.props.comments.map((comment) => {
  if (comment.hasComments === true) {
    return (
      <div key={comment.id}>
        <CommentItem className="MainComment" />
        {this.props.comments.map(commentReply => {
          if (commentReply.replyTo === comment.id) { 
            return (
              <CommentItem className="SubComment"/>
            )
          }
        })
        }
      </div>
    )
  } else {
     //return something here.
  }
});

edit you should take a look at Kris' answer for how to better implement what you are trying to do.

Solution 5 - Javascript

The most upvoted answer, from Kris Selbekk, it is totally right. It is important to highlight though that it takes a functional approach, you will be looping through the this.props.comments array twice, the second time(looping) it will most probable skip a few elements that where filtered, but in case no comment was filtered you will loop through the whole array twice. If performance is not a concern in you project that is totally fine. In case performance is important a guard clause would be more appropriated as you would loop the array only once:

return this.props.comments.map((comment) => {
  if (!comment.hasComments) return null; 
  
  return (
    <div key={comment.id}>         
      <CommentItem className="MainComment"/>
        {this.props.comments.map(commentReply => {             
          if (commentReply.replyTo !== comment.id) return null;
          
          return <CommentItem className="SubComment"/>
        })} 
    </div>          
  ) 
}

The main reason I'm pointing this out is because as a Junior Developer I did a lot of those mistakes(like looping the same array multiple times), so I thought i was worth mention it here.

PS: I would refactor your react component even more, as I'm not in favour of heavy logic in the html part of a JSX, but that is out of the topic of this question.

Solution 6 - Javascript

You can use the for loop like so:

for(let i = 0 ; i < comments.length; i++){
 if(comments[i].hasComments === true){
return (
       <div key={comments[i].id}>
        //content Here
      </div> // comment.id
        )
      }
     }

Solution 7 - Javascript

class Blog extends Component{
	render(){
		const posts1 = this.props.posts;
		//console.log(posts)
		const sidebar = (
			<ul>
				{posts1.map((post) => {
					//Must use return to avoid this error.
          return(
						<li key={post.id}>
							{post.title} - {post.content}
						</li>
					)
				})
			}
			
			</ul>
		);
		const maincontent = this.props.posts.map((post) => {
			return(
				<div key={post.id}>
					<h3>{post.title}</h3>
					<p>{post.content}</p>
				</div>
			)
		})
		return(
			<div>{sidebar}<hr/>{maincontent}</div>
		);
	}
}
const posts = [
  {id: 1, title: 'Hello World', content: 'Welcome to learning React!'},
  {id: 2, title: 'Installation', content: 'You can install React from npm.'}
];

ReactDOM.render(
  <Blog posts={posts} />,
  document.getElementById('root')
);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRamazan ChasygovView Question on Stackoverflow
Solution 1 - JavascriptZanonView Answer on Stackoverflow
Solution 2 - JavascriptKris SelbekkView Answer on Stackoverflow
Solution 3 - JavascriptCrsCaballeroView Answer on Stackoverflow
Solution 4 - JavascriptChrisView Answer on Stackoverflow
Solution 5 - JavascriptAnderson SaundersView Answer on Stackoverflow
Solution 6 - JavascriptSands QAView Answer on Stackoverflow
Solution 7 - JavascriptSrinivasan NView Answer on Stackoverflow