I’m on the web dev learning journey. Most recently I’ve been learning React Router and I’m excited to be close to building my first full stack (MERN) apps! The tutorial is building a basic contacts app.
I'm perplexed by a specific function in this tutorial that is supposed to update contact data. Here is the section of the tutorial where the function is called. Here is the module with the pertinent problem functions (additional functions were trimmed out for brevity):
import localforage from "localforage";
import { matchSorter } from "match-sorter";
import sortBy from "sort-by";
export async function updateContact(id, updates) {
await fakeNetwork();
let contacts = await localforage.getItem("contacts");
let contact = contacts.find(contact => contact.id === id);
if (!contact) throw new Error("No contact found for", id);
Object.assign(contact, updates);
await set(contacts);
return contact;
}
function set(contacts) {
return localforage.setItem("contacts", contacts);
}
The updateContact function doesn't add up to me because I see no place where the contacts variable, which is an array of objects, is being updated with the updated contact object, and I don't see an updated version of the contacts object being persisted to local storage, only what appears to be the same non-mutated/non-updated contacts object. The confusion is because the app actually does work, it does update the contact, but I do not understand how that is happening given this code.
If more context is needed please let me know...I don't think I can add too many additional code snippets because it thinks it's spam?
I've looked through the React Router documentation and I do not see how anything in the documentation could explain what I'm seeing. Using console.log in the function only made me more confused.
Any help is appreciated in pointing out what I might be missing!
CodePudding user response:
This code is mutating an object reference. Object.assign(contact, updates);
"merges" in the updates
into the contact
object which is a reference to an object in the contacts
array.
The
Object.assign()
static method copies all enumerable own properties from one or more source objects to a target object. It returns the modified target object.
The syntax is Object.assign(target, ...sources)
. See Object.assign for more details.
Once a specific contact
object is found, it's mutated, and the updated data is persisted back into localStorage.
export async function updateContact(id, updates) {
await fakeNetwork();
let contacts = await localforage.getItem("contacts");
// contact is reference to object in contacts
let contact = contacts.find(contact => contact.id === id);
if (!contact) throw new Error("No contact found for", id);
// mutate the contact object
Object.assign(contact, updates);
// persist updated data back to localStorage
await set(contacts);
return contact;
}
A more familiar "React-y" way might look something like:
export async function updateContact(id, updates) {
await fakeNetwork();
const contacts = await localforage.getItem("contacts");
const contact = contacts.find(contact => contact.id === id);
if (!contact) {
throw new Error("No contact found for", id);
}
const newContacts = contacts.map(contact => contact.id === id
? { ...contact, ...updates } // <-- create new object reference and merge
: contact
);
await set(newContacts);
return contact;
}