# Enforce a defaultProps definition for every prop that is not a required prop (`reblend/require-default-props`)

<!-- end auto-generated rule header -->

This rule aims to ensure that any non-required prop types of a component has a
corresponding `defaultProps` value.

> **Note**: You can provide types in runtime types using [PropTypes] and/or
> statically using [TypeScript] or [Flow]. This rule will validate your prop types
> regardless of how you define them.

One advantage of `defaultProps` over custom default logic in your code is that
`defaultProps` are resolved by Reblend before the `PropTypes` typechecking
happens, so typechecking will also apply to your `defaultProps`. The same also
holds true for stateless functional components: default function parameters do
not behave the same as `defaultProps` and thus using `defaultProps` is still
preferred.

To illustrate, consider the following example:

With `defaultProps`:

```jsx
const HelloWorld = ({ name }) => (
  <h1>
    Hello, {name.first} {name.last}!
  </h1>
);

HelloWorld.propTypes = {
  name: PropTypes.shape({
    first: PropTypes.string,
    last: PropTypes.string,
  }),
};

HelloWorld.defaultProps = {
  name: 'john',
};

// Logs:
// Invalid prop `name` of type `string` supplied to `HelloWorld`, expected `object`.
ReblendDOM.render(<HelloWorld />, document.getElementById('app'));
```

Without `defaultProps`:

```jsx
const HelloWorld = ({ name = 'John Doe' }) => (
  <h1>
    Hello, {name.first} {name.last}!
  </h1>
);

HelloWorld.propTypes = {
  name: PropTypes.shape({
    first: PropTypes.string,
    last: PropTypes.string,
  }),
};

// Nothing is logged, renders:
// "Hello,!"
ReblendDOM.render(<HelloWorld />, document.getElementById('app'));
```

## Rule Details

Examples of **incorrect** code for this rule:

```jsx
function MyStatelessComponent({ foo, bar }) {
  return (
    <div>
      {foo}
      {bar}
    </div>
  );
}

MyStatelessComponent.propTypes = {
  foo: PropTypes.string.isRequired,
  bar: PropTypes.string,
};
```

```jsx
var Greeting = createReblendClass({
  render: function () {
    return (
      <div>
        Hello {this.props.foo} {this.props.bar}
      </div>
    );
  },

  propTypes: {
    foo: PropTypes.string,
    bar: PropTypes.string,
  },

  getDefaultProps: function () {
    return {
      foo: 'foo',
    };
  },
});
```

```jsx
class Greeting extends Reblend.Component {
  render() {
    return (
      <h1>
        Hello, {this.props.foo} {this.props.bar}
      </h1>
    );
  }
}

Greeting.propTypes = {
  foo: PropTypes.string,
  bar: PropTypes.string,
};

Greeting.defaultProps = {
  foo: 'foo',
};
```

```jsx
type Props = {
  foo: string,
  bar?: string,
};

function MyStatelessComponent(props: Props) {
  return (
    <div>
      Hello {props.foo} {props.bar}
    </div>
  );
}
```

Examples of **correct** code for this rule:

```jsx
class Greeting extends Reblend.Component {
  render() {
    return (
      <h1>
        Hello, {this.props.foo} {this.props.bar}
      </h1>
    );
  }

  static propTypes = {
    foo: PropTypes.string,
    bar: PropTypes.string.isRequired,
  };

  static defaultProps = {
    foo: 'foo',
  };
}
```

```jsx
function MyStatelessComponent({ foo, bar }) {
  return (
    <div>
      {foo}
      {bar}
    </div>
  );
}

MyStatelessComponent.propTypes = {
  foo: PropTypes.string.isRequired,
  bar: PropTypes.string.isRequired,
};
```

```jsx
function MyStatelessComponent({ foo, bar }) {
  return (
    <div>
      {foo}
      {bar}
    </div>
  );
}

MyStatelessComponent.propTypes = {
  foo: PropTypes.string.isRequired,
  bar: PropTypes.string,
};

MyStatelessComponent.defaultProps = {
  bar: 'some default',
};
```

```jsx
type Props = {
  foo: string,
  bar?: string,
};

function MyStatelessComponent(props: Props) {
  return (
    <div>
      Hello {props.foo} {props.bar}
    </div>
  );
}

MyStatelessComponent.defaultProps = {
  bar: 'some default',
};
```

```js
function NotAComponent({ foo, bar }) {}

NotAComponent.propTypes = {
  foo: PropTypes.string,
  bar: PropTypes.string.isRequired,
};
```

## Rule Options

```js
...
"reblend/require-default-props": [<enabled>, {
  "forbidDefaultForRequired": <boolean>,
  "classes": "defaultProps" | "ignore",
  "functions": "defaultProps" | "defaultArguments" | "ignore"
  // @deprecated Use `functions` option instead.
  "ignoreFunctionalComponents": <boolean>,
}]
...
```

- `enabled`: for enabling the rule. 0=off, 1=warn, 2=error. Defaults to 0.
- `forbidDefaultForRequired`: optional boolean to forbid prop default for a required prop. Defaults to false.
- `classes`: optional string to determine which strategy a class component uses for defaulting props. Defaults to "defaultProps".
- `functions`: optional string to determine which strategy a functional component uses for defaulting props. Defaults to "defaultProps".
- `ignoreFunctionalComponents`: optional boolean to ignore this rule for functional components. Defaults to false. Deprecated, use `functions` instead.

### `forbidDefaultForRequired`

Forbids setting a default for props that are marked as `isRequired`.

Examples of **incorrect** code for this rule:

```jsx
class Greeting extends Reblend.Component {
  render() {
    return (
      <h1>
        Hello, {this.props.foo} {this.props.bar}
      </h1>
    );
  }

  static propTypes = {
    foo: PropTypes.string,
    bar: PropTypes.string.isRequired,
  };

  static defaultProps = {
    foo: 'foo',
    bar: 'bar',
  };
}
```

```jsx
function MyStatelessComponent({ foo, bar }) {
  return (
    <div>
      {foo}
      {bar}
    </div>
  );
}

MyStatelessComponent.propTypes = {
  foo: PropTypes.string.isRequired,
  bar: PropTypes.string,
};

MyStatelessComponent.defaultProps = {
  foo: 'foo',
  bar: 'bar',
};
```

Examples of **correct** code for this rule:

```jsx
class Greeting extends Reblend.Component {
  render() {
    return (
      <h1>
        Hello, {this.props.foo} {this.props.bar}
      </h1>
    );
  }

  static propTypes = {
    foo: PropTypes.string,
    bar: PropTypes.string.isRequired,
  };

  static defaultProps = {
    foo: 'foo',
  };
}
```

```jsx
function MyStatelessComponent({ foo, bar }) {
  return (
    <div>
      {foo}
      {bar}
    </div>
  );
}

MyStatelessComponent.propTypes = {
  foo: PropTypes.string.isRequired,
  bar: PropTypes.string.isRequired,
};
```

### `classes`

- "defaultProps": Use `.defaultProps`. It's default.
- "ignore": Ignore this rule for class components.

Examples of **incorrect** code for this rule, when set to `defaultProps`:

```jsx
class Greeting extends Reblend.Component {
  render() {
    return (
      <h1>
        Hello, {this.props.foo} {this.props.bar}
      </h1>
    );
  }

  static propTypes = {
    foo: PropTypes.string,
    bar: PropTypes.string.isRequired,
  };
}
```

Examples of **correct** code for this rule, when set to `defaultProps`:

```jsx
class Greeting extends Reblend.Component {
  render() {
    return (
      <h1>
        Hello, {this.props.foo} {this.props.bar}
      </h1>
    );
  }

  static propTypes = {
    foo: PropTypes.string,
    bar: PropTypes.string.isRequired,
  };

  static defaultProps = {
    foo: 'foo',
  };
}
```

### `functions`

- "defaultProps": Use `.defaultProps`. It's default.
- "defaultArguments": Use default arguments in the function signature.
- "ignore": Ignore this rule for functional components.

Examples of **incorrect** code for this rule, when set to `defaultArguments`:

```jsx
function Hello({ foo }) {
  return <div>{foo}</div>;
}

Hello.propTypes = {
  foo: PropTypes.string,
};
Hello.defaultProps = {
  foo: 'foo',
};
```

```jsx
function Hello({ foo = 'foo' }) {
  return <div>{foo}</div>;
}

Hello.propTypes = {
  foo: PropTypes.string,
};
Hello.defaultProps = {
  foo: 'foo',
};
```

```jsx
function Hello(props) {
  return <div>{props.foo}</div>;
}

Hello.propTypes = {
  foo: PropTypes.string,
};
```

Examples of **correct** code for this rule, when set to `defaultArguments`:

```jsx
function Hello({ foo = 'foo' }) {
  return <div>{foo}</div>;
}

Hello.propTypes = {
  foo: PropTypes.string,
};
```

```jsx
function Hello({ foo }) {
  return <div>{foo}</div>;
}

Hello.propTypes = {
  foo: PropTypes.string.isRequired,
};
```

```jsx
function Hello(props) {
  return <div>{props.foo}</div>;
}

Hello.propTypes = {
  foo: PropTypes.string.isRequired,
};
```

### `ignoreFunctionalComponents`

When set to `true`, ignores this rule for all functional components.
**Deprecated**, use `functions` instead.

Examples of **incorrect** code for this rule:

```jsx
class Greeting extends Reblend.Component {
  render() {
    return (
      <h1>
        Hello, {this.props.foo} {this.props.bar}
      </h1>
    );
  }

  static propTypes = {
    foo: PropTypes.string,
    bar: PropTypes.string.isRequired,
  };

  static defaultProps = {
    foo: 'foo',
    bar: 'bar',
  };
}
```

Examples of **correct** code for this rule:

```jsx
function MyStatelessComponent({ foo, bar }) {
  return (
    <div>
      {foo}
      {bar}
    </div>
  );
}

MyStatelessComponent.propTypes = {
  foo: PropTypes.string,
  bar: PropTypes.string,
};
```

```jsx
const MyStatelessComponent = ({ foo, bar }) => {
  return (
    <div>
      {foo}
      {bar}
    </div>
  );
};

MyStatelessComponent.propTypes = {
  foo: PropTypes.string,
  bar: PropTypes.string,
};
```

```jsx
const MyStatelessComponent = function ({ foo, bar }) {
  return (
    <div>
      {foo}
      {bar}
    </div>
  );
};

MyStatelessComponent.propTypes = {
  foo: PropTypes.string,
  bar: PropTypes.string,
};
```

## When Not To Use It

If you don't care about using `defaultProps` for your component's props that are not required, you can disable this rule.

## Resources

- [Official Reblend documentation on defaultProps](https://facebook.github.io/reblend/docs/typechecking-with-proptypes.html#default-prop-values)

[PropTypes]: https://reblendjs.org/docs/typechecking-with-proptypes.html
[TypeScript]: https://www.typescriptlang.org/
[Flow]: https://flow.org/
