React.js: establezca un valor predeterminado en un accesorio

3 minutos de lectura

Avatar de usuario de Dimitrios Desyllas
dimitrios desyllas

Compañeros, he creado este componente que crea un botón simple:

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

Y tengo otro componente que genera 2 botones:

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

Pero me sale el siguiente error:

TypeError: no se puede definir la propiedad “mensaje”: el objeto no es extensible

En la línea que dice:

        this.props.message="Hello"

en método setMessage del AppButton clase.

Editar 1

Generé la aplicación de reacción usando npm y yo package.json tiene el siguiente contenido

{
  "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"
  }
}

  • Nota al margen: me encantan tus alertas y mensajes. Realmente demuestra que te has esforzado mucho para que esto funcione de la manera que deseas. Sé que se siente tan bien.

    – Oh Dios por qué

    7 junio 2017 a las 17:58


  • Los puse por diversión. ¡Sin sudar en absoluto!

    – Dimitrios Desyllas

    7 junio 2017 a las 18:04

  • ¿Es eso válido? los dos nodos raíz?

    – Kevin B.

    7 junio 2017 a las 18:08

Avatar de usuario de Jesse Kernaghan
jesse kernaghan

Creo que accesorios predeterminados debe hacer lo que necesita:

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

De los documentos:

Se utilizarán defaultProps para garantizar que this.props.name tendrá un valor si no lo especificó el componente principal. La verificación de tipos de propTypes ocurre después de que se resuelven los valores predeterminados, por lo que la verificación de tipos también se aplicará a los valores predeterminados.

Editar para mayor claridad: No debería haber necesidad de ti setMessage en este caso.

  • A veces asigno valores predeterminados con la desestructuración de ES6 { names=[] }

    – Pedram marandi

    13 de febrero de 2018 a las 22:47

  • @Pedrammarandi sí, ese también es un buen enfoque si está creando un componente funcional sin la necesidad de enlaces de ciclo de vida.

    –Jesse Kernaghan

    16 de febrero de 2018 a las 18:21

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

Esto verificará el valor de prop y, si no está definido o es nulo, el mensaje predeterminado reemplazará a prop.

Avatar de usuario de Hyzyr
Hyzyr

para accesorios predeterminados puedes hacer esto

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

y use estas variables sin la palabra clave props (todavía puede usar props para valores de props no definidos)

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

Pero para su error, está bien manejar un error como:

{props.message ?? ''}

  • esto funciona bien, cuando es una cadena o un valor entero, ¿cómo funciona cuando el accesorio es una matriz con objetos anidados?

    – Mohamed Raza

    1 de septiembre de 2022 a las 21:44

¿Está utilizando React v.14 o superior? el objeto de accesorios ahora está congelado y no se puede cambiar. Puedes usar React.cloneElement en su lugar

Avatar de usuario de Facundo La Rocca
facundo la rocca

No puede establecer accesorios, debe usar el estado en su lugar.

Si necesita cambiar el valor, debe almacenarse en el estado debido a que los accesorios son estáticos.

Debes hacerlo de esta manera:

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

Y en el método de renderizado, utilícelo como:

{this.state.message}

Como recomendación, también deberías inicializar el estado con ese valor en el constructor:

constructor(props){
  super(props);

  this.state = {
    message: ''
  }
}

Lo mismo le pasará a setOnClick

Usted encontrará aquí una buena explicación sobre esto.

¿Ha sido útil esta solución?