This question already has answers here:
What is the concept of Array.map?
(10 answers)
Closed 3 years ago.
I have a class component that uses the map method to access an array of objects. I Then use an implicit return to turn each object into a component. From my understanding the map method can only take an array, then pass a function to change the array.I don't understand why my code below works?
class App extends Component {
state = {
players: [
{
name: "Guil",
id: 1
},
{
name: "Treasure",
id: 2
},
{
name: "Ashley",
id: 3
},
{
name: "James",
id: 4
}
]
};
render() {
return (
<div className="scoreboard">
{this.state.players.map( player =>
<Player
name={player.name}
id={player.id}
key={player.id.toString()}
removePlayer={this.handleRemovePlayer}
/>
)}
</div>
);
}
}
From MDN
The map() method creates a new array populated with the results of calling a provided function on every element in the calling array.
The map() never change the original array but just create a new array according to the provided function.
In your code, the map() method creates a new array of Player components(the result of the provided callback).
The way you used is the same as what you said:"take an array, then pass a function to change the array".Here is the arrow function and an implicit return action.
Related
This question already has answers here:
React doesn't rerender on an array state update
(2 answers)
React re-render not showing updated state array
(3 answers)
Correct modification of state arrays in React.js
(19 answers)
Right way to clone objects / arrays during setState in React
(7 answers)
Why is useState not triggering re-render?
(9 answers)
Closed last month.
I have an object employees that gets updated from user input through setEmployees() inside a function. I don't understand why for loop does not work but map() works to update the value on the webpage. I am not sure if this is react thing or useState() thing or maybe something else that I missed or did not know. Any idea? Thank you.
The employee object that gets updates from useState hook:
const [employees, setEmployees] = useState([
{
id: 0,
name: "Jason",
role: "Engineer",
img: 'https://images.pexels.com/photos/2598024/pexels-photo-2598024.jpeg'
},
{
id: 1,
name: "Abby",
role: "Manager",
img: 'https://images.pexels.com/photos/2598024/pexels-photo-2598024.jpeg'
}
]);
The case where I use for loop but it does not work:
function updateEmployee(id, newName, newRole) {
// Using for loop to update values
const updatedEmployees = employees
for (let i of updatedEmployees) {
if (i.id == id) {
i.name = newName
i.role = newRole
}
}
console.log(updatedEmployees) // updatedEmployees has been successfully updated
setEmployees(updatedEmployees) // object `employees` values have been updated but the update does not show on the webpage
}
The case where I use map() and it works:
function updateEmployee(id, newName, newRole) {
// Using map() to update values
const updatedEmployees = employees.map((employee) => {
if (id == employee.id) {
return {...employee, name: newName, role: newRole}
}
return employee
})
setEmployees(updatedEmployees) // object `employees` values have been updated and also update the values shown on the webpage
}
This question already has answers here:
ECMAScript 6 arrow function that returns an object
(6 answers)
Closed 2 years ago.
I am running the following in node and can't understand why one works and why the other doesn't. Here I have an array s where s = [1, 2, 3, 4]. I want to map each number to an object. I've been trying this for a long time:
s.map(i => {name: i})
which returns a list of undefined.
Finally I realized it worked with parenthesis:
s.map(i => ({name: i}))
This provides the output I want: [ { name: 1 }, { name: 2 }, { name: 3 }, { name: 4 } ]
I feel like there is a JavaScript concept I am not understanding. Why does this not work?
This is because => { represents a block function, not returning an object.
Wrapping the object in parentheses does nothing, it simply interrupts that pattern => {, meaning it's interpreted as a concise arrow function rather than a block arrow function, and you can return the object.
So, if you want to return an object, you can either wrap it in parentheses (this is the easiest way):
s.map(i => ({ name: i }));
Or use a block function:
s.map(i => {
return { name: i };
});
(on a side note, you can make your function more concise by passing in name as the map parameter name:
s.map(name => ({ name }));
As pointed out by Tomasz below, the reason that your first attempt returned a list of undefined was because name: is the syntax for a label in JavaScript - and you were just labelling name: then stating the variable i - so your code basically looked like this ES5:
s.map(function(i) {
name: i
// No return so it returns `undefined`
});
This question already has answers here:
Is this a good way to clone an object in ES6?
(10 answers)
What is the most efficient way to deep clone an object in JavaScript?
(67 answers)
Closed 2 years ago.
I am a newbie in React. I need some help to solve this issue
Code:
this.state={
testState: {
testArray: [
{ name: "bob" },
{ name: "alice" },
{ name: "john" }
]
}
}
testFn = () => {
let a;
a = { ...this.state.testState }; //using spread operator to copy the object instead of referencing
a.testArray.map((obj) => {
obj.name = "React is awesome"
})
console.log(this.state.testState)
}
Output:
testArray: Array(3)
0: {name: "React is awesome"}
1: {name: "React is awesome"}
2: {name: "React is awesome"}
I have to modify a without altering the state. But here, the state is also changed along with the iteration.
How can I solve this problem?
The spread operator only does a shallow copy
To guarantee a full object copy use
const copiedState = JSON.parse(JSON.stringify(yourState))
Better solution
Sove it at the source. Don't make deep state, its actually a key part of writing objects in the state. You should keep them very shallow. In this case you are already way deep with Obj -> Array -> Obj.
This question already has answers here:
How to iterate over a JavaScript object?
(19 answers)
Closed 5 years ago.
I have an object in array like the following:
bears: [
{
Yogi: "123kg",
Pooh: "110kg",
Grizly: "112kg",
BooBoo: "200kg",
Polar: "100kg",
}
]
`
What is the best way to iterate through such object in order to display both names and values in the row, like returning something in the type of: <p>${name} ${value}</p>
So I would display:
Yogi 123kg
Pooh 110kg
Grizly 112kg
BooBoo 200kg
Polar 100kh
It's an array containing an object, not an object. Anyway just get the first item of the array.
This should work:
Object.keys(bears[0]).map(key => <p>{`${key} ${bears[0][key]}`}</p>);
I think that the JSON object's structure itself is wrong.
It should be structured like this:
var bears = [{
name: "Yogi",
weight: "123kg"
}, {
name: "Pooh",
weight: "110kg"
}, {
name: "Grizly",
weight: "112kg"
}, {
name: "BooBoo",
weight: "200kg"
}]
Then you can go ahead and iterate through it using a for loop inside of the render() method like this.
render() {
var bearElements = [];
for (var bearIndex = 0; bearIndex < bears.length; bearIndex++) {
bearElements.push(
<p>{`${bears[bearElements].name}` `${bears[bearElements].weight}`}</p>
)
}
return (
<div>{bears}</div>
);
}
This question already has answers here:
How do I check if an object has a specific property in JavaScript?
(31 answers)
Closed 5 years ago.
I have an enum in which I store some UI element values that look like this:
const uiElementAttributes = {
1: {
id: 1,
color: 'red',
icon: 'icon-something.png'
},
2: {
id: 2,
color: 'yellow',
icon: 'icon-something-else.png'
},
3: {
id: 3,
color: 'blue',
icon: 'icon-this-item.png'
},
99: {
id: 99,
color: 'black',
icon: 'icon-black.png'
}
};
I have a function that will return the correct object from the enum based on id passed to my function. My question is how do I check if a value is defined in an enum?
Here's the function:
const getAttributes (id) => {
// How do I check to see if the id is in the enum?
if(checkIfIdIsInEnum) {
return uiElementAttributes[id];
} else {
return uiElementAttributes[99];
}
};
UPDATE: I'm trying the suggested answer. It does look pretty straight forward but looks like when webpack transpiles my code to vanilla JS, it adds default at the end of my enum which is undefined. Any idea what may be causing this -- see below? As you can see, the id value I'm passing is 1 so it should be able to find the value 1 in my enum object.
And here's the actual enum object:
Here's the actual function code:
UPDATE 2:
I resolved the issue by importing the enum within curly braces -- see below:
import {calendarEvents} from '../../enums/calendarEvents';
In this special case, you could access the property and if the result is falsey, then take the default property 99.
const getAttributes = id => uiElementAttributes[id] || uiElementAttributes[99];
Otherwise, you could use the in operator, or the suggested Object#hasOwnProperty.