189

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>
)    
3
  • 3
    @AbdennourTOUMI Please don't destroy the default initialiser syntax! Commented Dec 12, 2017 at 16:00
  • Thank you @Bergi. never mind! I thought it is a wrong syntax. Is it ? Commented Dec 12, 2017 at 17:47
  • 3
    @AbdennourTOUMI No, it's the syntax for default values. You changed it to object literal syntax, which is invalid with string/boolean literals in parameters. Commented Dec 12, 2017 at 18:01

11 Answers 11

137

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.

Sign up to request clarification or add additional context in comments.

5 Comments

so, how it should be?
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 stackoverflow.com/questions/41488537/…
Thank you. For those using the eslint rule "require-default-props" and using ES6 default parameters, you can disable the rule for now: github.com/croutonn/next-template/issues/27 .eslintrc.json: "rules": { "react/require-default-props": "off" }
@fjplaurr Better to disable it for functional components in particular: "react/require-default-props": ["error", { "functions": "ignore" }] (or "functions": "defaultArguments" to force destructuring, but I found it actually forced it in some cases I didn't want).
What if you use function Test(props: PropsWithChildren<propTypes>) { What is the best practice to set default parameter for some attributes of props in this case?
47

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.

4 Comments

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?
@AlexanderNied defaultProps is evaluated before checking for propTypes. also, as mentioned in @fforw response, destructuring defaults do not apply here.
@AlexanderNied and that small difference is very important for some more complex connected components, see my answer below.
This answer is now outdated, since default props on functional components will eventually be deprecated (see my answer below).
15

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>
)

1 Comment

I liked this approach. Wondering if the name should be DEFAULT_PROPS instead of defaultProps since these are constants and won't change.
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>
}

Comments

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>
    );
};

Comments

2

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:'',
}

Comments

1

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

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

2 Comments

This is not an answer. It should be a comment.
@T3rm1 It means the default parameters is officially recommended. Why do you think it's not an answer?
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

Comments

0

you can use a destructured approach, example :

  const { inputFormat = 'dd/mm/yyyy', label = 'Default Text', ...restProps } = props;

Comments

0

This is not an ideal solution but works for basic components with type support

const defaultProps = {
  title: false,
  subTitle: false,
  updateFunction: null as Function | null,
};

const Component = (inputProps: Partial<typeof defaultProps>) => {
  const props = {...defaultProps, ...inputProps};
  const {title} = props;

  return ...
};

export default Component;

Comments

-1

enter image description here

Here is why I dislike this forced change...

enter image description here

The .defaultProps allow for re-usable functional components without requiring an input value for every...single...usage. The default parameters do not :(

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.