1

I have a super simple react element like this below:

const Stores = ({ stores }) => {
  const renderStores = () => Object.keys(stores).map(store => {    
    return (
      <div key={store}>
        { store }        
      </div>
    )
  })

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

It takes in stores (it's a POJO, not an array) as a prop and iterates through its keys to display the name of the store.

The problem is when I write react elements this way, the stores isn't defined or could be null at this point in my app and this causes Object.keys to throw an error because you can't iterate through undefined or null.

What I want is the behavior of this react component to render nothing if stores is undefined or null.

I would like to avoid the need to wrap my renderStores function and check for undefined/null:

const Stores = ({ stores }) => {
  const renderStores = () => {
    if (stores) {
      return Object.keys(stores).map(store => {    
        return (
          <div key={store}>
            { store }        
          </div>
        )
      })  
    } else {
      return <div></div>
    }    
  }

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

But this isn't easy on the eyes.

I could instead do this:

return (
  <div>
    { stores ? renderStores() : '' }
  </div>
)

But this seems like boilerplate.

Is there a better way or a common convention to protect Object.keys() from throwing an error when undefined/null is passed in to be iterated in a react element?

0

2 Answers 2

2

I think the way you are managing it initially is the correct approach. I the concern is how that looks, you can clean things up a bit in this way:

const Stores = ({ stores }) => {
  const renderStores = () => {
    if !(stores) return null;
    return Object.keys(stores).map(store => (
      <div key={store}>
        { store }        
      </div>
    ))    
  }

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

This will return a null when there are no stores and render just the <div></div>.

You could also add a default in the arguments like this:

    const Stores = ({ stores = {} }) => {

This would allow you to essentially return nothing from the map of the keys.

The third option, would be to not render stores from the parent if stores is null. This would be the cleanest option for you potentially.

// parent.js

{ data ? <Stores stores=data /> : null }

// stores.js
const Stores = ({ stores }) => (
  <div>
    { 
      Object.keys(stores).map(store => (
        <div key=store>
          {store}        
        </div>
      ))
    }
  </div>
)

If you have an empty state you need to maintain, you can pass that in falsey return of the conditional.

I do this quite often multiple ways.

Sign up to request clarification or add additional context in comments.

1 Comment

I may not have exactly the correct syntax for the last example - let me know if it doesn't work and I can update.
1

If stores is null or undefined, it's falsy, and you could use a logical OR to just use an empty object instead, which would have no keys, an no iteration would happen

Object.keys(stores||{}).map(...

you wouldn't get an empty element though, you'd need a condition for that

1 Comment

If you want to use this approach - just use a default - const Stores = ({ stores = {} }) => { It's much more obvious what is going on.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.