Chris Scott
Chris Scott

Reputation: 91

How to destructure an object that is stored as a state value

Within a React App component, I am calling an API and storing the response within a local state. I then want to destructure the object that is stored in that state, but I can't just destructure right below the useEffect because it will throw an error before the call is completed.

Also, I don't want to break up the object within the useEffect, because I want the entire response for other things.

Here is an example:

const MyComponent = () => {

  const [calledObj, setCalledObj] = useState({})

  useEffect(() => {
    //Calling API here and setting object response as calledObj State
    setCalledObj(apiResponse)
  }, []);

  //This will throw an error when the API response has not been sent back yet.//
  // While this would be easy to write the whole path in the return, the actual path is really long.//
  const { name } = calledObj.person

  return (<div>{name}</div>)
}

Where can I destructure or how can I work around this?

Upvotes: 3

Views: 1162

Answers (3)

Soli Huayhua
Soli Huayhua

Reputation: 1

You can initialize your state with:

const [calledObj, setCalledObj] = useState({person: {}})

And this will put undefined in 'name' but is not breaking your code.

Upvotes: 0

ray
ray

Reputation: 27245

You can use optional chaining and/or the nullish coelescing operator to work around it.

Note: IE doesn't support either of these, but babel will polyfill them.

const { name } = calledObj?.person ?? {};
  1. The optional chaining (the ?. in calledObj?.person) prevents it from blowing up if calledObj is undefined.
  2. The nullish coalescing operator (??) returns {} if calledObj.person isn't there.

With this combination the right side is guaranteed to evaluate to an object, so the destructuring on the left never blows up.

let calledObject; // undefined;

// name is undefined, but it doesn't blow up.
const { name: name1 } = calledObject?.person ?? {};

console.log(`name 1: ${name1}`); // name 1: undefined

// ----------------

// now it's an object, but doesn't have a person property
calledObject = {};

// name is still undefined, still doesn't blow up.
const { name: name2 } = calledObject?.person ?? {};

console.log(`name 2: ${name2}`); // name 1: undefined

// ----------------

// with person.name present…
calledObject.person = { name: 'joe' };

const { name: name3 } = calledObject?.person ?? {};

// …it works as you'd expect
console.log(`name 3: ${name3}`); // name 3: 'joe'

Upvotes: 5

codemonkey
codemonkey

Reputation: 7905

Depending on what you want your name variable to default to on first render, I guess you could do something like this:

  const { name } = calledObj.person ? calledObj.person : {name: ''}

Upvotes: 0

Related Questions