React.js: Set a Default value into a prop

JavascriptReactjsEcmascript 6

Javascript Problem Overview


Fellows I have made this Component that creates a simple Button:

class AppButton extends Component {

  setOnClick() {
    if(!this.props.onClick && typeof this.props.onClick == 'function') {
      this.props.onClick=function(){ alert("Hello"); }
    }
  }

  setMessage() {
    if(!this.props.message){
        this.props.message="Hello"
    }
  }

  render(){
    this.setOnClick()
    this.setMessage()
    return (
      <button onClick={this.props.onClick}>{this.props.message}</button>
    )
  }
}

And I have an another Component that renders 2 Buttons:

class App extends Component {
  render() {
    return (
          <AppButton onClick={function(){ alert('Test Alert') } } message="My Button" />
          <AppButton />
    );
  }
}

But I get the following error:

> TypeError: can't define property "message": Object is not extensible

On the line that says:

        this.props.message="Hello"

in method setMessage of the AppButton class.

Edit 1

I generated the react application using npm and me package.json has the following content

{
  "name": "sample",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "react": "^15.5.4",
    "react-dom": "^15.5.4"
  },
  "devDependencies": {
    "react-scripts": "1.0.7"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  }
}

Javascript Solutions


Solution 1 - Javascript

I believe that defaultProps should do what you need:

import PropTypes from 'prop-types';

class AppButton extends Component {
 render(){
    return (
      <button onClick={this.props.onClick}>{this.props.message}</button>
    )
  }
};

AppButton.propTypes = {
  message: PropTypes.string,
  onClick: PropTypes.func
};

AppButton.defaultProps = {
  message: 'Hello',
  onClick: function(){ alert("Hello"); }
};

From the docs: >The defaultProps will be used to ensure that this.props.name will have a value if it was not specified by the parent component. The propTypes typechecking happens after defaultProps are resolved, so typechecking will also apply to the defaultProps.

Edit for clarity: There should be no need for you setMessage in this instance.

Solution 2 - Javascript

return (
      <button onClick={this.props.onClick}>{this.props.message || "Default text"}</button>
);

This will check the value of prop and if it is undefined or null, the default message will replace the prop.

Solution 3 - Javascript

Are you using React v.14 or above? the props object is now frozen and cant be changed. You can use React.cloneElement instead

Solution 4 - Javascript

You cant set props, you must use state instead.

If you need to change the value, then it should be stored in the state due to props are static.

You should do it in this way:

this.setState({message: 'your message'});

And in the render method use it as:

{this.state.message}

As a recomendation, you should also initialize the state with that value in the constructor:

constructor(props){
  super(props);

  this.state = {
    message: ''
  }
}

The same will happend to setOnClick

You will find here a good explanation about this.

Solution 5 - Javascript

for deafault props you can do this

 const { 
     message = '', 
     onClick = (e)=>{} 
 } = props;

and use these variables without props keyword (you can still use props for not defined props values)

<button onClick={onClick}>{message}</button> 
{props.value}

But for your error it is just fine to handel error like:

{props.message ?? ''}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDimitrios DesyllasView Question on Stackoverflow
Solution 1 - JavascriptJesse KernaghanView Answer on Stackoverflow
Solution 2 - JavascriptnetoguimaraesView Answer on Stackoverflow
Solution 3 - JavascriptAlejandro C.View Answer on Stackoverflow
Solution 4 - JavascriptFacundo La RoccaView Answer on Stackoverflow
Solution 5 - JavascriptHyzyrView Answer on Stackoverflow