Map return multi components - javascript

i'm trying to maping two component but i get this error :
Module build failed: SyntaxError: Unexpected token (72:7)
import AlertListItem from '~/components/Dashboard/AlertListItem'
import AlertItem from '~/components/Dashboard/AlertItem'
let items
if (result) {
items = result.map((item, index) =>
return(
<div>
<AlertListItem key={item.id} item={item} onPopup={this._onSelect} index={index} />
<AlertItem id={item.id} item={item} onClose={this._onDeselect} />
</div>
)
)
any solution ?

When using a concise arrow function (no {}), you don't use the return keyword; the body of the concise arrow function is a single expression, but return is a statement. (You also have a ) instead of } closing the if block.)
So:
import AlertListItem from '~/components/Dashboard/AlertListItem'
import AlertItem from '~/components/Dashboard/AlertItem'
let items
if (result) {
items = result.map((item, index) =>
<div>
<AlertListItem key={item.id} item={item} onPopup={this._onSelect} index={index} />
<AlertItem id={item.id} item={item} onClose={this._onDeselect} />
</div>
)
}
Example (this also has the change called out in the "Side Note" below):
// Setup:
const AlertListItem = props =>
<div>{props.children}</div>;
const AlertItem = props =>
<div>Item #{props.id}</div>;
const result = [
{id: 1}, {id: 2}, {id: 3}
];
// Your corrected code (with the event handlers removed,
// don't need them for the example)
let items;
if (result) {
items = result.map((item, index) =>
<div key={item.id}>
<AlertListItem item={item} index={index} />
<AlertItem id={item.id} item={item} />
</div>
)
}
// Show it
ReactDOM.render(
<div>{items}</div>,
document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
Just for completeness, here's a simpler example of a concise arrow function:
array.sort((a, b) => a - b);
Note how the body is just the expression a - b.
And the equivalent verbose one:
array.sort((a, b) => { return a - b; });
Since we've used {...}, it's a full function body block, which contains statements, so we use return to return a value.
Side note: You need to put the key on the div, not the AlertListItem; if you use the non-minified library, it'll warn you about getting key wrong. I've moved key in my example above.

You are missing a curly braces for map:
items = result.map((item, index) => {...}

Related

Javascript Object destructuring syntax confusion [duplicate]

I recently came across this piece of code on a website
const List = ({ items }) => (
<ul className="list">
{items.map(item => <ListItem item={item} />)}
</ul>
);
Why have they wrapped the items in curly braces and is it a prop
This is called a "destructuring". Actually, you're passing an object as an argument to the function, but the destructuring uses only the named properties of the object.
const destructuring = ({ used }) => console.log(used);
const properties = {
unused: 1,
used: 2,
};
destructuring(properties); // 2
You can even use it for creating variables.
const properties = {
name: 'John Doe',
age: 21,
};
const { name, age } = properties;
console.log(name, age); // John Doe 21
I'm a newbie to React, but I think yes, items is a prop, and passing {items} as an argument destructures the props object, and thus the function uses only the prop items, in order to simplify the code. This way you can use items in the functional component, instead of props.items. For example, I tested a similar situation in the following code. Using destructuring looks like this:
const ListItem = ({content}) => (
<li>{content}</li>
);
...
<ListItem key={index} content={content} />
Whereas if you used props it would look like this:
const ListItem = (props) => (
<li>{props.content}</li>
);
...
<ListItem key={index} content={content} />
So for your example, using props would look like this:
const List = (props) => (
<ul className="list">
{props.items.map(item => <ListItem item={item} />)}
</ul>
);
Meanwhile, destructuring allows you to simplify to items, rather than props.items which is what was being done in your original code:
const List = ({ items }) => (
<ul className="list">
{items.map(item => <ListItem item={item} />)}
</ul>
);
Cheers!
--Omar

React | Gatsby: Components inside or outside main page component

While learning how to use react-beautiful-dnd library, I've found that (when I'm building the library required structure) if I define components outside the main app, it works on React but it does not work on Gatsby (development), it starts to work but then errors appear
But if I move those components inside the main app, then it also works on Gatsby
The example code:
export default () => {
const [elements, setElements] = useState(myElements)
const onDragEnd = result => {
const { destination, source} = result
if (!destination) return
if (destination.droppableId === source.droppableId && destination.index === source.index) return
const new_elements = reorder(elements, source.droppableId, destination.droppableId, source.index, destination.index)
setElements(new_elements)
}
const Columns = ({ arr }) =>
arr.map((col, i) => (
<Droppable droppableId={col.columnId} key={i}>
{(provided, snapshot) => (
<Ul ref={provided.innerRef}>
<Elements arr={col.items} />
{provided.placeholder}
</Ul>
)}
</Droppable>
))
const Elements = ({ arr }) =>
arr.map((el, j) => (
<Draggable draggableId={el.id} index={j} key={j}>
{(provided, snapshot) => (
<Li ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
{el.text}
</Li>
)}
</Draggable>
))
return (
<DragDropContext onDragEnd={onDragEnd}>
<Grid>
<Columns arr={myElements} />
</Grid>
</DragDropContext>
)
}
So if Columns and Elements are defined outside, it's not working (but it is with React)
Why is this happening?
(the sandbox: https://codesandbox.io/s/using-react-beautiful-dnd-with-hooks-bfwzl?fontsize=14&hidenavigation=1&theme=dark)
As said in the docs https://github.com/atlassian/react-beautiful-dnd/blob/master/docs/api/draggable.md#keys-for-a-list-of-draggable-
Your key should not include the index of the item
Once changed this, it works as expected
<Droppable droppableId={col.columnId} key={col.columnId}>
<Draggable draggableId={el.id} index={j} key={el.id}>

How to use .map() to iterate an object and create number of <Item />

I have created an object with label and value keys. Now What I want to do is create for each item in the object by using .map() function.
// my object
const ageData = [...Array(71)].map((x, i) => ({ label: i + 10, value: i + 10 }));
//My object looks like 0: {label: 10, value: 10} 1: {label: 11, value: 11}
//What I want to create
<Item label=10 value=10 />
<Item label=11 value=11 />
//My current non-working solution
ageData.map(obj => <Item label=obj.label value=obj.value />)
As commenters mentioned above the syntax needs a bit work. It could be something like this using a functional component:
const Items = props => {
return (
<div>
{props.someArray.map(obj => (<Item label={obj.label} value={obj.value} />))}
</div>
)
}
Then return the following from a functional component, or your render method, where you want to display the items:
<Items someArray={ageData} />
Where ageDate is your array.
Note that you were missing the {} around your expressions inside the JSX code, as well as parentheses around the JSX expression your were returning from your map.
Bonus:
You can write your functional component shorter like this, if you just need it to return an expression like above:
const Items = props => (
<div>
{props.someArray.map(obj => (<Item label={obj.label} value={obj.value} />))}
</div>
)

Not looping through data with ES6 Map function

I have array that i want to map through the values and i can not get the ES6 map to work correctly. Below is my code.
Thanks for the help.
0: "FOLDER2"
1: "FOLDER3
renderNames = () => {
const listItems = this.props.clickedFolderNames
.map((number, index) => <ListItem key={index} value={number} />);
return (
<ul>
{listItems}
</ul>
);
}
You need to wrap your anonymous function block in curly brackets and return a value if you are splitting it over multiple lines:
.map((number,index) => {
return (<ListItem key={index}
value={number} />)
});
return (
<ul>
{listItems}
</ul>
);
}

react and conditional rendering

Currently I am using the following code to conditionally render some HTML based on hasLocations variable.
Code works, but I wish to know if there is a better way to achieve the same result, for example, I am not sure having two return is a good practice.
const Finder = ({ locations, onLocationClick }) => {
let hasLocations = locations.length > 0
if (hasLocations) {
return (
<ul>
{locations.map((location, index) =>
<Location
key={index}
{...locations[index]}
onLocationClick={() => onLocationClick(location)}
/>
)}
</ul>
)
} else {
return (null)
}
}
Alternatively you chould use conditional rendering. For your example, this would look like this.
const Finder = ({ locations, onLocationClick }) => {
return (
<ul>
{locations.length > 0 &&
locations.map((location, index) =>
<Location
key={index}
{...locations[index]}
onLocationClick={() => onLocationClick(location)}
/>
)}
</ul>
);
}
EDIT: My solution would be the following.
I would avoid adding any logic in it(AKA presentational component). So it would become
const Finder = ({ locations, onLocationClick }) => {
return (
<ul>
locations.map((location, index) =>
<Location
key={index}
{...locations[index]}
onLocationClick={() => onLocationClick(location)}
/>
)
</ul>
);
}
And when you need to use it you can do something like this:
return (
<div>
{locations.length > 0 && Finder}
</div>
);
There's nothing wrong with using multiple returns in a function, but when you do it's good practice to put a "default" return as the last statement in the function to make it more apparent that the function always returns something.
In your case that means you could move your return (null) (no need to wrap null in brackets, btw) statement out of the else clause and just put it as the last statement of the function.
It's also possible to use a single return statement with ternary in your return, like this:
return locations.length > 0 ? (
<ul>
{locations.map((location, index) =>
<Location
key={index}
{...locations[index]}
onLocationClick={() => onLocationClick(location)}
/>
)}
</ul>
) : null

Categories