new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

React · Learn · all subjects

state/objects

28 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Updating objects in state requires creating a new object

State can hold any kind of JavaScript value, including objects. However, you must not mutate objects directly in state. When you want to update an object in state, you must create a new object (or copy an existing one) and then update state to use the new object. Use the spread syntax (...) to copy objects before modifying them.

Spread syntax for updating nested objects

To update a nested object in state, use the spread syntax at each level. For example, to update a nested property: setPerson({ ...person, artwork: { ...person.artwork, title: e.target.value } }). This creates a new person object and a new artwork object with the updated title, while preserving all other properties.

Using Immer library to simplify object updates

The Immer library can reduce repetitive code when updating objects in state. With useImmer hook, you can write code that looks like mutation but actually produces immutable updates. For example: updatePerson(draft => { draft.name = e.target.value; }) instead of creating new objects manually with spread syntax.

Cannot update single field in object state without copying others

When state is an object, you cannot update only one field without explicitly copying the other fields. For example, you cannot do setPosition({ x: 100 }) because it would remove the y property. Instead, use setPosition({ ...position, x: 100 }) to update only x while keeping y.

Example: Moving dot with grouped state

```js import { useState } from 'react'; export default function MovingDot() { const [position, setPosition] = useState({ x: 0, y: 0 }); return ( <div onPointerMove={e => { setPosition({ x: e.clientX, y: e.clientY }); }} style={{ position: 'relative', width: '100vw', height: '100vh', }}> <div style={{ position: 'absolute', backgroundColor: 'red', borderRadius: '50%', transform: `translate(${position.x}px, ${position.y}px)`, left: -10, top: -10, width: 20, height: 20, }} /> </div> ) } ``` This example shows grouping x and y coordinates into a single position state object that updates together on pointer movement.

Example: Flattened state structure for nested hierarchies

```js export const initialTravelPlan = { 0: { id: 0, title: '(Root)', childIds: [1, 42, 46], }, 1: { id: 1, title: 'Earth', childIds: [2, 10, 19, 26, 34] }, 2: { id: 2, title: 'Africa', childIds: [3, 4, 5, 6, 7, 8, 9] }, // ... more places }; ``` Instead of nested childPlaces arrays within objects, use a flat structure where each place holds an array of child IDs and a top-level object maps IDs to places. This makes updates like deleting nested items much simpler.

Use Set for multiple item selection state

When managing multiple selected items, use a Set in state to store IDs. This allows very fast lookups using the has() method to check if an item is selected, which is more efficient than checking an array.

Set toggle pattern with handleToggle

To toggle items in a Set, create a copy, check if the item exists using has(), delete it if present, or add it if absent, then update state with the modified copy.

Example: Set-based multi-select with React

function handleToggle(toggledId) { const nextIds = new Set(selectedIds); if (nextIds.has(toggledId)) { nextIds.delete(toggledId); } else { nextIds.add(toggledId); } setSelectedIds(nextIds); } This creates a copy of the Set, toggles an item by ID, and updates state. The component checks selection status using selectedIds.has(letter.id) for fast lookups.

Reasons for not mutating state in React

Mutating state prevents debugging (console.log can be clobbered), breaks optimization strategies that compare previous and current state with ===, prevents new React features that depend on treating state as a snapshot, makes features like Undo/Redo harder to implement, and requires unnecessary special handling. React allows simple implementations because it does not rely on mutation.

Objects are references, not nested containers

Objects that appear nested in code are actually separate objects pointing to each other via properties. An object like {name: 'Alice', artwork: {title: 'Blue'}} consists of two separate objects where the first object's artwork property points to the second object. Multiple variables can reference the same inner object, so mutating it affects all references to it.

useImmer hook installation and usage

To use Immer with React, run npm install use-immer, then import useImmer from 'use-immer'. Replace useState with useImmer. The hook returns [state, updateFunction] where updateFunction takes a callback receiving a draft object. Example: const [person, updatePerson] = useImmer(initialValue); updatePerson(draft => {draft.name = 'new';});

Example: Updating object with spread syntax

setPerson({ ...person, firstName: e.target.value });

Example: Updating nested object with spread syntax

setPerson({ ...person, artwork: { ...person.artwork, city: 'New Delhi' } });

Mutating objects in state prevents re-renders

When you mutate an object that is already in React state, React does not trigger a re-render because React has no way to know the object changed. For example, directly modifying position.x = e.clientX will not cause a re-render. Instead, you must create a new object and pass it to the state setter function to trigger a re-render.

Example: Using Immer for nested updates

import { useImmer } from 'use-immer'; const [person, updatePerson] = useImmer({ name: 'Niki', artwork: { title: 'Blue Nana', city: 'Hamburg' } }); function handleCityChange(e) { updatePerson(draft => { draft.artwork.city = e.target.value; }); }

Pitfall: Mutating state from previous render

Directly modifying an object in state (like position.x = 5) does not trigger a re-render. React only detects state changes when you call the state setter function. The mutation happens silently, and the UI does not update until an unrelated state change causes a re-render, making the bug difficult to notice.

Pitfall: Forgetting to spread all properties

When using spread syntax, if you forget to spread the original object, you will lose properties. For example, setPerson({lastName: e.target.value}) without ...person will create an object with only the lastName field, losing firstName and other properties.

Pitfall: Shared object references in nested structures

If multiple state variables or properties reference the same object, mutating that object affects all of them. For example, if both shape.position and initialPosition point to the same object, mutating shape.position will also change initialPosition, causing unexpected side effects.

Example: Single event handler with computed property names

function handleChange(e) { setPerson({ ...person, [e.target.name]: e.target.value }); } This handler works for multiple input fields with different 'name' attributes.

Treat objects in state as immutable

Although objects in React state are technically mutable in JavaScript, you should treat them as if they were immutable. This means always creating a new object when you need to update state, rather than modifying the existing object directly.

Use object spread syntax to copy and update objects

To update an object in state while keeping other fields, use the spread syntax: setPerson({...person, firstName: e.target.value}). This creates a shallow copy of the object and allows you to override specific properties without mutating the original.

Object spread syntax is shallow

The object spread syntax (...obj) only copies one level deep. For nested objects, you will need to use spread syntax at multiple levels to ensure immutability. For example, updating a nested property requires spreading both the parent and child objects.

Updating nested objects requires copying all levels

To update a nested object property like person.artwork.city, you must create a new artwork object with the updated city, then create a new person object that contains the new artwork: setPerson({...person, artwork: {...person.artwork, city: 'New Delhi'}}).

Use computed property names for dynamic object updates

You can use bracket notation [e.target.name] inside object literals to dynamically set properties based on input names: setPerson({...person, [e.target.name]: e.target.value}). This allows a single event handler to update multiple fields.

Local mutation is acceptable

Mutating a newly created object that no other code references yet is acceptable. For example, const nextPosition = {}; nextPosition.x = e.clientX; is fine because the object has not been exposed to other code. The issue only arises when mutating objects that are already in state or referenced elsewhere.

Immer simplifies nested object updates

Immer is a library that lets you write mutating code syntax while producing immutable updates under the hood. Install with npm install use-immer, then use useImmer instead of useState. Call the update function with a draft object: updatePerson(draft => {draft.artwork.city = 'Lagos';}). Immer handles creating the necessary copies automatically.

How Immer works with Proxy

Immer provides a special Proxy object called 'draft' that records mutations you make to it. You can mutate the draft freely without affecting the original state. Immer internally detects which parts of the draft changed and produces a completely new object containing your edits.

Give your agent this brain