James Donnelly
James Donnelly

Reputation: 128771

Applying logic to defaultProps

I have a component which has one required property and one optional property. The optional property acts as an override mechanism which, if not present, defaults to a value derived from the required property. It's set up like this:

function fruitColour(fruit) {
  switch (fruit) {
    case 'banana':
      return 'yellow';
  }
}

const Fruit = (props) => {
  const { type } = props;
  let { colour } = props;

  colour = colour || fruitColour(type);

  return <p>A yummy {colour} {type}!</p>
}

This allows me to have a mature, ripe banana:

<Fruit type='banana' />

Or a younger, unripe banana:

<Fruit type='banana' colour='green' />

The project I'm working on enforces that if a prop value isn't read as a constant it must be given a default value within defaultProps. Currently I'm doing this:

Fruit.defaultProps = {
  colour: ''
}

But this is silly because my component's logic already handles the default state.

Am I stuck with this pattern, or is it possible to read the type property within defaultProps in order to do something like this:

Fruit.defaultProps = {
  colour: (props) => fruitColour(props.type)
}

...and then read the colour property as a constant as well, dropping the defaulting logic?

Upvotes: 5

Views: 1453

Answers (1)

Ori Drori
Ori Drori

Reputation: 191916

Since you are using a stateless component, use destructuring with defaults instead of defaultProps. Since the default argument is evaluated each time the function called, you can call fruitColour(fruit), and use it's result as the default.

const Fruit = ({ type, color = fruitColour(type) }) => (
  <p>A yummy {color} {type}!</p>
);

ReactDOM.render(
  <div>
    <Fruit type="banana" color="red" />
    
    <Fruit type="banana" />
  </div>,
  document.getElementById('app')
);

function fruitColour(fruit) {
  switch (fruit) {
    case 'banana':
      return 'yellow';
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="app"></div>

Upvotes: 2

Related Questions