Reputation: 972
I am following the official redux tutorial with this code (it works!)
const TodoList = ( {todos} ) => (
<ul>
{ todos.map( todo =>
<li key={todo.id}>{todo.name}</li>
)}
</ul>
)
I have been playing around with the syntax and this also works:
const TodoList = ( {todos} ) => (
<ul>
{ todos.map( todo => {
return <li key={todo.id}>{todo.name}</li>
})}
</ul>
)
but this does not work:
const TodoList = ( {todos} ) => (
<ul>
{ todos.map( todo => {
<li key={todo.id}>{todo.name}</li>
})}
</ul>
)
Can anyone explain the difference between them and why the third one fails?
Upvotes: 1
Views: 87
Reputation: 8542
If you look at the documentation for map, you have to return a value, which will be the new value in the new array created by the map function. This means that return
has to exist in the callback of your map function, whether stated explicitly or implicitly.
The arrow functions you have declared as a callback (e.g todo => <li key={todo.id}>{todo.name}</li>
) in the first and the second example are equal. You may want to refer to different ways to declare arrow functions in the documentation here.
In the third example however, you are returning a block of code without a return statement. The default behavior of the javascript runtime is to return undefined. Here are some code to demonstrate this behavior:
const test = () => { var a; /* a block of code with no return statement */ }
const a = test();
console.log(a);
Hence, the elements of the array that is returned from the map function in your third example will undefined. This is the main reason why your todos are not getting rendered in your list.
Upvotes: 0
Reputation: 1281
The difference has to do with how you specify the body of the arrow function.
{ todos.map( todo =>
<li key={todo.id}>{todo.name}</li>
)}
Is an expression within the body and by default does not need a return statement,
<ul>
{ todos.map(todo => <li key={todo.id}>{todo.name}</li>) }
</ul>
When defined within a block, a return statement needs to be included .
Upvotes: 0
Reputation: 1163
Here, You nicely added a block statement , In block statement implicit return is syntactically ambiguous, now it returns undefined. In ES6 arrow function return is implicit under some circumstances. Like You added a block it made undefined. You can find more detail in this post.
Upvotes: 0
Reputation: 15914
Because the arrow function
todo => {
<li key={todo.id}>{todo.name}</li>
}
returns nothing and you will get an array that contains undefined
s ( based on the length of todos
). For example:
const ary = [1, 2, 3].map(el => { console.log(el) })
console.log(ary) // [undefined, undefined, undefined]
You must return something in the callback of .map()
If the callback only contains 1 expression and returns immediately, you can omit the { }
and return
.
const foo = () => {
return 'foo'
}
is equal to
const foo = () => 'foo'
So now you can:
const TodoList = ( {todos} ) => (
<ul>
{ todos.map( todo => (
<li key={todo.id}>{todo.name}</li>
))}
</ul>
)
also the ( )
is not a must, you can omit that if you preferred:
const TodoList = ( {todos} ) => (
<ul>
{ todos.map(todo => <li key={todo.id}>{todo.name}</li>) }
</ul>
)
Upvotes: 3