By the end of this tutorial, you’ll use _.updateWith() to transform nested values while controlling how missing path segments are built.
01
Core syntax
_.updateWith(object, path, updater, customizer)
02
Updater fn
Transforms current value at path.
03
Customizer
Builds intermediate containers only.
04
Object / Array
Pass constructors for nested shapes.
05
vs _.update()
When defaults vs custom path building.
06
Real patterns
Increment, toggle, create missing paths.
Fundamentals
What Is _.updateWith()?
_.updateWith() combines _.update() with the customizer hook from _.setWith(). The updater transforms the value at a path; the optional customizer decides how missing intermediate containers are created while Lodash walks to that path.
💡
Two functions, two jobs
updater = transform the leaf value. customizer = build missing {} or [] along the way. Do not mix them up.
Use it when you need both value transformation (increment, toggle, uppercase) and explicit control over nested structure—especially array-heavy paths like rows[0].cells[1].count.
Foundation
📝 Syntax
The signature adds an optional fourth argument—the customizer:
javascript
_.updateWith(object, path, updater, [customizer])
Syntax Rules
object — target object (mutated in place).
path — same formats as _.update: dot string, brackets, or key array.
updater — (currentValue) => newValue; transforms the value at the path.
Lodash splits the path into segments, same as _.update.
Input
2
Customizer creates containers
When a segment is missing, the customizer produces the next object or array. Return undefined for defaults.
Build
3
Updater transforms leaf
The current value at the path is passed to your updater; its return value is assigned at the leaf.
Transform
=
⚙️
Path updated
The same object reference is returned with the transformed nested value.
Important
📝 Notes
The updater transforms the leaf value; the customizer builds intermediates only.
Return undefined from the customizer to fall back to Lodash defaults (same as _.update).
_.updateWith mutates the target object like _.update.
Passing Object or Array as the customizer is a common shorthand for container creation.
For simple transforms on existing paths, _.update() is usually enough.
Pair conceptually with _.setWith()—updateWith adds an updater; setWith assigns a literal.
Wrap Up
Conclusion
_.updateWith() merges the updater pattern from _.update() with the customizer hook from _.setWith(). Use it when you need both value transformation and explicit control over nested container creation.
Remember: updater transforms the leaf, customizer shapes the path. Next in the series: _.values().
Use _.updateWith when you need both transform and custom containers
Handle undefined in updaters when paths may not exist yet
Return existing nsValue from the customizer when reusing containers
Prefer plain _.update when the path already exists and defaults suffice
Clone first when immutability is required
❌ Don’t
Expect the customizer to transform the final value—that is the updater’s job
Confuse updateWith customizer with mergeWith merge rules
Reach for updateWith when _.update already fits
Forget that the updater must return the new leaf value
Assume it is immutable like spread-based state updates
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about _.updateWith()
Use these when transforms need custom path building.
5
Core concepts
⚙️01
Updater
Leaf transform.
Core
⚙️02
Customizer
Builds path.
Hook
🗃️03
Object / Array
Constructor shorthand.
Pattern
🔀04
vs update
Defaults vs control.
Compare
⚠️05
Mutates
Like _.update().
Note
❓ Frequently Asked Questions
_.updateWith() reads the value at a nested path, passes it to an updater function, and writes the return value back—like _.update(). It also accepts a customizer that controls how missing intermediate containers are created along the path.
_.update() uses Lodash defaults when creating missing path segments. _.updateWith() adds an optional customizer so you can force Array, Object, or custom logic for intermediates—same relationship as set vs setWith.
It builds missing intermediate containers while walking the path: (nsValue, key, object) => container. It does not transform the final value—that is the updater's job.
The current value at the path, or undefined if the path does not exist yet. Return the new value to assign at the leaf.
Lodash falls back to default behavior: numeric index keys get arrays, other keys get plain objects—same as _.update() and _.set().
Yes. It mutates the target in place and returns the same object reference. Clone first when immutability matters.
Did you know?
_.updateWith() pairs an updater with a setWith-style customizer. The customizer never transforms the leaf—only the updater does. Some old examples incorrectly use the customizer like a value transformer; keep the two roles separate.