31
loading...
This website collects cookies to deliver better user experience
const person = { name: 'Jarvis', age: 32 };
person.age = 33;
function copyPerson(person, newName, newAge) {
const newPerson = person;
newPerson.name = newName;
newPerson.age = newAge;
return newPerson;
}
const jarvis = { name: 'Jarvis', age: 32, arms: 2, legs: 2 };
const stanley = copyPerson(jarvis, 'Stanley', 27);
console.log(stanley);
// { age: 27, arms: 2, legs: 2, name: "Stanley" }
console.log(jarvis);
// { age: 27, arms: 2, legs: 2, name: "Stanley" }
copyPerson
function, we accidentally assigned newPerson
a reference to the same person
object. Since they reference the same object, mutating newPerson
also mutates person
.person
object using the spread operator and simultaneously overwriting the name
and age
properties:function copyPerson(person, newName, newAge) {
const newPerson = {
...person,
name: newName,
age: newAge,
};
return newPerson;
}
function copyPerson(person, newName, newAge) {
const newPerson = { ...person };
newPerson.name = newName;
newPerson.age = newAge;
return newPerson;
}
function App() {
const [person, setPerson] = useState({ name: 'Jarvis', age: 32 });
return <PersonCard person={person} />;
}
PersonCard
component will re-render if person
changes.PersonCard
component will re-render person
references a new object. Again, we can get ourselves in trouble if we mutate person
rather than creating a new object.function App() {
const [person, setPerson] = useState({ name: 'Jarvis', age: 32 });
function incrementAge() {
person.age++;
setPerson(person);
}
return (
<>
<PersonCard person={person} />
<button onClick={incrementAge}>Have a birthday</button>
</>
);
}
age
property of the person
object and then try to set the person
state to that object. The problem is that it's not a new object, it's the same person
object as the prevous render! React's diffing algorithm sees no change to the person
reference and doesn't re-render the PersonCard
.person
. Then, we can either accomplish the task by mutating the new object or some other means:function App() {
const [person, setPerson] = useState({ name: 'Jarvis', age: 32 });
function incrementAge() {
const newPerson = { ...person };
newPerson.age++;
setPerson(newPerson);
}
return (
<>
<PersonCard person={person} />
<button onClick={incrementAge}>Have a birthday</button>
</>
);
}
newPerson
is bad because we're using React, make sure to check your assumptions! There's nothing wrong here: newPerson
is a variable scoped to the incrementAge
function. We're not mutating something React is tracking, and therefore the fact that we're "in React" doesn't come into play here.function updateItem(index, newValue) {
const newItems = items.map((el, i) => {
if (i === index) {
return newValue;
}
return el;
});
setItems(newItems);
}
function updateItem(index, newValue) {
const newItems = [...items];
newItems[index] = newValue;
setItems(newItems);
}
const data = [
{ id: 56, parentId: 62 },
{ id: 81, parentId: 80 },
{ id: 74, parentId: null },
{ id: 76, parentId: 80 },
{ id: 63, parentId: 62 },
{ id: 80, parentId: 86 },
{ id: 87, parentId: 86 },
{ id: 62, parentId: 74 },
{ id: 86, parentId: 74 },
];
id
and then the id
of its parent node (parentId
). Our code to build a tree can be as follows:// Get array location of each ID
const idMapping = data.reduce((acc, el, i) => {
acc[el.id] = i;
return acc;
}, {});
let root;
data.forEach((el) => {
// Handle the root element
if (el.parentId === null) {
root = el;
return;
}
// Use our mapping to locate the parent element in our data array
const parentEl = data[idMapping[el.parentId]];
// Add our current el to its parent's `children` array
parentEl.children = [...(parentEl.children || []), el];
});
data
array once to create a mapping of where each element is in the array. Then, we do another pass through the data
array and, for each element, we use the mapping to locate its parent in the array. Finally, we mutate the parent's children
property to add the current element to it.console.log(root)
, we end up with the full tree:{
id: 74,
parentId: null,
children: [
{
id: 62,
parentId: 74,
children: [{ id: 56, parentId: 62 }, { id: 63, parentId: 62 }],
},
{
id: 86,
parentId: 74,
children: [
{
id: 80,
parentId: 86,
children: [{ id: 81, parentId: 80 }, { id: 76, parentId: 80 }],
},
{ id: 87, parentId: 86 },
],
},
],
};