172

In a React functional component, which is the better approach to set default props, using Component.defaultProps, or using the default parameters on the function definition, examples:

Default props:

const Component = ({ prop1, prop2 }) => (
  <div></div>
)

Component.defaultProps = {
  prop1: false,
  prop2: 'My Prop',
}

Default parameters:

const Component = ({ prop1 = false, prop2 = 'My Prop' }) => (
  <div></div>
)    
Iago Dahlem
  • 2,659
  • 3
  • 12
  • 12

9 Answers9

122

defaultProps on functional components will eventually be deprecated (as per Dan Abramov, one of the core team), so for future-proofing it's worth using default parameters.

Tom
  • 2,734
  • 2
  • 22
  • 39
  • 3
    so, how it should be? – ValRob Jun 11 '19 at 12:27
  • 1
    It means, use default parameters and not "defaultProps", if you care about the maintainability of your project. Someone actually cross-referenced this answer in my own reply, see https://stackoverflow.com/questions/41488537/react-defaultprops-vs-es6-default-params-when-destructuring-performances-issu/42733457?noredirect=1#comment102950610_42733457 – Vadorequest Oct 09 '19 at 15:34
  • 3
    Thank you. For those using the eslint rule "require-default-props" and using ES6 default parameters, you can disable the rule for now: https://github.com/croutonn/next-template/issues/27 .eslintrc.json: "rules": { "react/require-default-props": "off" } – fjplaurr Nov 30 '20 at 11:34
45

In general (ES6), the second way is better.

In specific (in React context), the first is better since it is a main phase in the component lifecycle, namely, the initialization phase.

Remember, ReactJS was invented before ES6.

jdunning
  • 1,356
  • 1
  • 14
  • 26
Abdennour TOUMI
  • 87,526
  • 38
  • 249
  • 254
  • 3
    Could you expand on what it is about using `defaultProps` that makes it preferable to default parameters in the context of React? Is there something fundamental about how they are handled under the hood in React, or is it preferred more for the purposes of maintaining convention? – Alexander Nied Jan 31 '19 at 16:08
  • 1
    @AlexanderNied `defaultProps` is evaluated _before_ checking for `propTypes`. also, as mentioned in @fforw response, destructuring defaults do not apply here. – Capi Etheriel Mar 06 '19 at 22:15
  • 1
    @AlexanderNied and that small difference is very important for some more complex connected components, see my answer below. – Jkarttunen Apr 27 '19 at 13:00
  • 10
    This answer is now outdated, since default props on functional components will eventually be deprecated (see my answer below). – Tom Jun 04 '19 at 11:38
11

First one can cause some hard-to-debug performance problems, especially if you are using redux.

If you are using objects or lists or functions, those will be new objects on every render. This can be bad if you have complex components that check the component idenitity to see if rerendering should be done.

const Component = ({ prop1 = {my:'prop'}, prop2 = ['My Prop'], prop3 = ()=>{} }) => {(
  <div>Hello</div>
)}

Now that works fine, but if you have more complex component and state, such as react-redux connected components with database connection and/or react useffect hooks, and component state, this can cause a lot of rerending.

It is generally better practice to have default prop objects created separately, eg.

const Component = ({prop1, prop2, prop3 }) => (
  <div>Hello</div>
)

Component.defaultProps = {
  prop1: {my:'prop'},
  prop2: ['My Prop'],
  prop3: ()=>{}
}

or

const defaultProps = {
  prop1: {my:'prop'},
  prop2: ['My Prop'],
  prop3: ()=>{}
}
const Component = ({
  prop1 = defaultProps.prop1,
  prop2 = defaultProps.prop2
  prop3 = defaultProps.prop3
 }) => (
  <div>Hello</div>
)
Jkarttunen
  • 6,764
  • 4
  • 27
  • 29
  • I liked this approach. Wondering if the name should be `DEFAULT_PROPS` instead of `defaultProps` since these are constants and won't change. – cyonder Jun 07 '23 at 17:43
3

Shameless Plug here, I'm the author of with-default-props.

If you are a TypeScript user, with-default-props might help you, which uses higher order function to provide correct component definition with defaultProps given.

Eg.

import { withDefaultProps } from 'with-default-props'

type Props = {
    text: string;
    onClick: () => void;
};

function Component(props: Props) {
    return <div onClick={props.onClick}>{props.text}</div>;
}

// `onClick` is optional now.
const Wrapped = withDefaultProps(Component, { onClick: () => {} })


function App1() {
    // ✅
    return <Wrapped text="hello"></Wrapped>
}

function App2() {
    // ✅
    return <Wrapped text="hello" onClick={() => {}}></Wrapped>
}

function App3() {
    // ❌
    // Error: `text` is missing!
    return <Wrapped onClick={() => {}}></Wrapped>
}
Zen
  • 5,065
  • 8
  • 29
  • 49
3

I don't know if is the best way but it works :)

export interface ButtonProps {
    children: ReactNode;
    type?: 'button' | 'submit';
}

const Button: React.FC<ButtonProps> = ({ children, type = 'button' }) => {
    return (
        <button type={type}
        >
            {children}
        </button>
    );
};
Whisher
  • 31,320
  • 32
  • 120
  • 201
1

Here is the official announcement regarding the deprecation of the defaultProps.

https://github.com/reactjs/rfcs/pull/107

Jimmy Ko
  • 857
  • 1
  • 8
  • 20
1

Here is what I used to prefer so far. I am sharing an example of the ProgressBar of react-bootstrap that uses default props

const [formProgress, setFormProgress] = useState(10);

<BSProgressBar now={formProgress} striped={true} />

BSProgressBar.jsx

import ProgressBar from 'react-bootstrap/ProgressBar';

export default function BSProgressBar(props){
    const {now, min, striped, className} = { ...defaultProps, ...props};
    return (<>
        <ProgressBar 
            now={now}
            min={min}
            className={className}
            max={defaultProps.max}
            striped={striped}
        />
    </>)
}

const defaultProps = {
    min:0,
    now:0,
    max:100,
    striped:false,
    className:'',
}
Ram Chander
  • 1,088
  • 2
  • 18
  • 36
0

Even maybe you ask, why not use sth like below code with props || value instead of defaultProps :

class SomeComponent extends React.Component {
  render() {
    let data = this.props.data || {foo: 'bar'}
    return (
      <div>rendered</div>
    )
  }
}

// SomeComponent.defaultProps = {
//   data: {foo: 'bar'}
// };

ReactDOM.render(
  <AddAddressComponent />,
  document.getElementById('app')
)

But remember defaultProps make code more readable , specially if you have more props and controlling them with || operator could make your code looks ugly

SayJeyHi
  • 1,559
  • 4
  • 19
  • 39
0

you can use a destructured approach, example :

  const { inputFormat = 'dd/mm/yyyy', label = 'Default Text', ...restProps } = props;
Luis
  • 1,242
  • 11
  • 18