146
votes

I use the code below to set default props on a React component but it doesn't work. In the render() method, I can see the output "undefined props" was printed on the browser console. How can I define a default value for the component props?

export default class AddAddressComponent extends Component {

render() {
   let {provinceList,cityList} = this.props
    if(cityList === undefined || provinceList === undefined){
      console.log('undefined props')
    }
    ...
}

AddAddressComponent.contextTypes = {
  router: React.PropTypes.object.isRequired
}

AddAddressComponent.defaultProps = {
  cityList: [],
  provinceList: [],
}

AddAddressComponent.propTypes = {
  userInfo: React.PropTypes.object,
  cityList: PropTypes.array.isRequired,
  provinceList: PropTypes.array.isRequired,
}
9

9 Answers

146
votes

You forgot to close the Class bracket.

class AddAddressComponent extends React.Component {
  render() {
    let {provinceList,cityList} = this.props
    if(cityList === undefined || provinceList === undefined){
      console.log('undefined props')
    } else {
      console.log('defined props')
    }

    return (
      <div>rendered</div>
    )
  }
}

AddAddressComponent.contextTypes = {
  router: React.PropTypes.object.isRequired
};

AddAddressComponent.defaultProps = {
  cityList: [],
  provinceList: [],
};

AddAddressComponent.propTypes = {
  userInfo: React.PropTypes.object,
  cityList: React.PropTypes.array.isRequired,
  provinceList: React.PropTypes.array.isRequired,
}

ReactDOM.render(
  <AddAddressComponent />,
  document.getElementById('app')
)
<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" />
95
votes

For those using something like babel stage-2 or transform-class-properties:

import React, { PropTypes, Component } from 'react';

export default class ExampleComponent extends Component {
   static contextTypes = {
      // some context types
   };

   static propTypes = {
      prop1: PropTypes.object
   };

   static defaultProps = {
      prop1: { foobar: 'foobar' }
   };

   ...

}

Update

As of React v15.5, PropTypes was moved out of the main React Package (link):

import PropTypes from 'prop-types';

Edit

As pointed out by @johndodo, static class properties are actually not a part of the ES7 spec, but rather are currently only supported by babel. Updated to reflect that.

15
votes

First you need to separate your class from the further extensions ex you cannot extend AddAddressComponent.defaultProps within the class instead move it outside.

I will also recommend you to read about the Constructor and React's lifecycle: see Component Specs and Lifecycle

Here is what you want:

import PropTypes from 'prop-types';

class AddAddressComponent extends React.Component {
  render() {
    let { provinceList, cityList } = this.props;
    if(cityList === undefined || provinceList === undefined){
      console.log('undefined props');
    }
  }
}

AddAddressComponent.contextTypes = {
  router: PropTypes.object.isRequired
};

AddAddressComponent.defaultProps = {
  cityList: [],
  provinceList: [],
};

AddAddressComponent.propTypes = {
  userInfo: PropTypes.object,
  cityList: PropTypes.array.isRequired,
  provinceList: PropTypes.array.isRequired,
}

export default AddAddressComponent;
10
votes

You can also use Destructuring assignment.

class AddAddressComponent extends React.Component {
  render() {

    const {
      province="insertDefaultValueHere1",
      city="insertDefaultValueHere2"
    } = this.props

    return (
      <div>{province}</div>
      <div>{city}</div>
    )
  }
}

I like this approach as you don't need to write much code.

5
votes

use a static defaultProps like:

export default class AddAddressComponent extends Component {
    static defaultProps = {
        provinceList: [],
        cityList: []
    }

render() {
   let {provinceList,cityList} = this.props
    if(cityList === undefined || provinceList === undefined){
      console.log('undefined props')
    }
    ...
}

AddAddressComponent.contextTypes = {
  router: React.PropTypes.object.isRequired
}

AddAddressComponent.defaultProps = {
  cityList: [],
  provinceList: [],
}

AddAddressComponent.propTypes = {
  userInfo: React.PropTypes.object,
  cityList: PropTypes.array.isRequired,
  provinceList: PropTypes.array.isRequired,
}

Taken from: https://github.com/facebook/react-native/issues/1772

If you wish to check the types, see how to use PropTypes in treyhakanson's or Ilan Hasanov's answer, or review the many answers in the above link.

4
votes

You can set the default props using the class name as shown below.

class Greeting extends React.Component {
  render() {
    return (
      <h1>Hello, {this.props.name}</h1>
    );
  }
}

// Specifies the default values for props:
Greeting.defaultProps = {
  name: 'Stranger'
};

You can use the React's recommended way from this link for more info

4
votes

For a function type prop you can use the following code:

AddAddressComponent.defaultProps = {
    callBackHandler: () => {}
};

AddAddressComponent.propTypes = {
    callBackHandler: PropTypes.func,
};
4
votes

If you're using a functional component, you can define defaults in the destructuring assignment, like so:

export default ({ children, id="menu", side="left", image={menu} }) => {
  ...
};
1
votes
class Example extends React.Component {
  render() {
    return <h1>{this.props.text}</h1>;
  }
}

Example.defaultProps = { text: 'yo' };