JS/ES6: Destructuring of undefined
I'm using some destructuring like this:
const { item } = content
console.log(item)
But how should I handle content === undefined
- which will throw an error?
The 'old' way would look like this:
const item = content && content.item
So, if content
is undefined -> item
will also be undefined.
Can I do something similar using destructuring?
You can use short circuit evaluation to supply a default if content
is a falsy value, usually undefined
or null
in this case.
const content = undefined
const { item } = content || {}
console.log(item) // undefined
A less idiomatic (see this comment) way is to spread the content into an object before destructuring it, because null
and undefineds
values are ignored.
const content = undefined
const { item } = { ...content }
console.log(item) // undefined
If you are destructuring function params you can supply a default (= {}
in the example).
Note: The default value would only be applied if the destructured param is undefined
, which means that destructuring null
values will throw an error.
const getItem = ({ item } = {}) => item
console.log(getItem({ item: "thing" })) // "thing"
console.log(getItem()) // undefined
try {
getItem(null)
} catch(e) {
console.log(e.message) // Error - Cannot destructure property `item` of 'undefined' or 'null'.
}
Or even set a default value for the item
property if the input object doesn't contain the property
const getItem = ({ item = "default" } = {}) => item
console.log(getItem({ item: "thing" })) // "thing"
console.log(getItem({ foo: "bar" })) // "default"
const { item } = Object(content)
One can unpack undefined value, but can't unpack from undefined.
Fixing it is as easy as setting the default params value.
Example:
(() => {
// prepare payload
const PAYLOAD = {
holdingJustThis: 1
};
// lets unpack the payload and more
const {
holdingJustThis,
itIsGoingToBeUndefined,
itCouldThrowButWont: {
deep
} = {} // this will secure unpacking "deep"
} = PAYLOAD;
console.log({
holdingJustThis
});
console.log({
itIsGoingToBeUndefined // logs {itIsGoingToBeUndefined:undefined}
});
console.log({
deep // logs {deep:undefined}
});
})()
Destructuring the nested object is clean and short but sucks when source property is null
or undefined
in right side object
let say we have
const {
loading,
data: { getPosts },
} = useQuery(FETCH_POSTS_QUERY);
Solution 1
if we have data object but no getPosts
then we can use:
(Setting default at each level)
const {
loading,
data: { getPosts = [] } = { getPosts: [] },
} = useQuery(FETCH_POSTS_QUERY);
Solution 2:
if event data
is undefined
then:
const {
loading,
data: { getPosts } = { getPosts: [] },
} = useQuery(FETCH_POSTS_QUERY);