8

I'm using es6 object destructuring to provide default parameters to a function.

function mapStateToProps({ shops: { cakeShop: {}, pieShop: {} }) {
  return {
    CakeShopName: shops.cakeShop.Name,
    PieShopName: shops.pieShop.Name
  }
}

The problem with the above is that if I call

mapStateToProps({})

The code throws Cannot read property 'Name' of undefined. The nested objects on shops are not set to their default values and the code has a null reference.

How can I make sure that the nested objects within shops are being set to the right default value, even if shops itself is defined?

2
  • I don't think you can do that with destructuring, it works only if you are sure... Commented Mar 17, 2017 at 12:01
  • Sound like you were confusing destructuring with default values. Your syntax destructures an argument object, but doesn't actually introduce any parameter identifiers. Commented Mar 17, 2017 at 12:57

3 Answers 3

14

Sound like you were confusing destructuring with default values. Your syntax destructures an argument object, but doesn't actually introduce any parameter identifiers. There is no shops variable in your function scope.

I'll assume that you actually wanted to introduce cakeShop and pieShop variables, and provide them with defaults. To do that, you'd write

function mapStateToProps({ shops: { cakeShop = {}, pieShop = {} }) {
// short for             { shops: { cakeShop: cakeShop = {}, pieShop: pieShop = {} }) {
// parameter names (that will be bound):      ^^^^^^^^                ^^^^^^^
  return {
    CakeShopName: cakeShop.Name,
    PieShopName: pieShop.Name
  }
}

You might also use

function mapStateToProps({ shops: { cakeShop: {name: CakeShopName} = {}, pieShop: {name: PieShopName} = {} }) {
  return {CakeShopName, PieShopName};
}
Sign up to request clarification or add additional context in comments.

2 Comments

This is right. As far as I can see, this is the same as @estus answer but with cleaner syntax (without the extra two = {} at the end?)
@glcheetham Those defaults are needed when you want to be able to call the function with an object that has no shops property or without any argument at all.
7

To handle default values for nested objects, it should be

function mapStateToProps({ shops: { cakeShop = {}, pieShop = {} } = {} } = {}) {
...
}

4 Comments

This works but now shops is undefined within the function scope. What if I need to access alot of props on shops?
The code in the question doesn't explain that. cakeShop, etc can be used as cakeShop.Name. If you really need shops then don't use param destructuring and do const { cakeShop = {}, pieShop = {} } = shops instead. You cannot have both shops and cakeShop from param destructuring at the same time.
you can: {shops, shops: { cakeShop = {}, pieShop = {} } = {} } = {} - keep in mind that if e.g. cakeShop is null, false or 0 your default will be set
@Dude Defaults are applied to undefined only. It's the opposite, if a value can be null then defaults won't be applied, if they are desirable then destructuring is unsuitable in this case.
1

I know this question is about destructuring but for anyone interested I'm leaving another option here using lodash or underscore:

function mapStateToProps(shops) {
  _.defaultsDeep(shops, {
    cakeShop: {
      Name: "Kiki's CakeShop"
    }, 
    pieShop: {}
  })

  return {
    CakeShopName: shops.cakeShop.Name, // defaults to "Kiki's CakeShop"
    PieShopName: shops.pieShop.Name // undefined if not specified
  }
}

Comments

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.