Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 790
James Donnelly Avatar asked Oct 29 '22 02:10

James Donnelly


1 Answers

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>
like image 158
Ori Drori Avatar answered Nov 11 '22 13:11

Ori Drori