Pregunta Reaccionar - cambiar la entrada valor predeterminado pasando accesorios


Considera este ejemplo:

var Field = React.createClass({
    render: function () {
        // never renders new value...
        return (
            <div>
                <input type="text" defaultValue={this.props.value || ''} />
            </div>
        );
    }
});

var App = React.createClass({
    getInitialState: function () {
        return {value: 'Hello!'};
    },

    changeTo: function (str) {
        this.setState({value: str});
    },

    render: function () {
        return (
            <div>
                <Field value={this.state.value} />
                <button onClick={this.changeTo.bind(null, 'Whyyyy?')}>Change to "Whyyyy?"</button>
                <button onClick={this.changeTo.bind(null, void 0)}>Change to undefined</button>
            </div>
        );
    }
});

React.render(
    <App />,
    document.getElementById('app')
);

Quiero pasar el valor a defaultValue como apoyo del componente de entrada tonto. Sin embargo, nunca lo vuelve a renderizar.


13
2018-06-09 09:15


origen


Respuestas:


Como se mencionó una respuesta previa, defaultValue solo se establece en la carga inicial de un formulario. Después de eso, no se actualizará de forma "natural" porque la intención fue solo establecer un valor predeterminado inicial.

Puede evitar esto si lo necesita pasando un key al componente envoltorio, como en su Field o App componente, aunque en circunstancias más prácticas, probablemente sería un form componente. Un bien key sería un valor único para el recurso que se pasa al formulario, como el ID almacenado en la base de datos, por ejemplo.

En su caso simplificado, puede hacer esto en su campo de procesamiento:

<div key={this.props.value}>
    <input type="text" defaultValue={this.props.value || ''} />
</div>

En un caso de formulario más complejo, algo así podría obtener lo que desea si, por ejemplo, su acción onSubmit se envió a una API pero se mantuvo en la misma página:

const Form = ({item, onSubmit}) => {
  return (
    <form onSubmit={onSubmit} key={item.id}>
      <label>
        First Name
        <input type="text" name="firstName" defaultValue={item.firstName} />
      </label>
      <label>
        Last Name
        <input type="text" name="lastName" defaultValue={item.lastName} />
      </label>
      <button>Submit!</button>
    </form>
  )
}

Form.defaultProps = {
  item: {}
}

Form.propTypes = {
  item: PropTypes.object,
  onSubmit: PropTypes.func.isRequired
}

Cuando usamos entradas de formulario no controladas, generalmente no nos importan los valores hasta después de que se envían, por eso es más ideal forzar una nueva representación cuando realmente desea actualizar los valores predeterminados (después del envío, no de cada cambio de la entrada individual).

Si también está editando el mismo formulario y teme que la respuesta de la API pueda regresar con valores diferentes, podría proporcionar una clave combinada de algo así como id plus timestamp.


32
2018-01-31 16:13



valor por defecto solo funciona para la carga inicial. Después de eso, no se actualizará. Necesita mantener el estado para usted Campo componente:

var Field = React.createClass({
    //transfer props to state on load
    getInitialState: function () {
        return {value: this.props.value};
    },
    //if the parent component updates the prop, force re-render
    componentWillReceiveProps: function(nextProps) {
         this.setState({value: nextProps.value});
    },
    //re-render when input changes
    _handleChange: function (e){
        this.setState({value: e.target.value});
    },
    render: function () {
        // render based on state
        return (
            <div>
                <input type="text" onChange={this._handleChange} 
                                   value={this.state.value || ''} />
            </div>
        );
    }
});

11
2018-05-12 23:03



Estoy bastante seguro de que esto tiene que ver con Entradas controladas vs. no controladas.

Si entiendo correctamente, ya que su <input> es incontrolado (no define un value atributo), entonces el valor siempre se resolverá con el valor con el que se inicializa. En este caso Hello!.

Para superar este problema, puede agregar un value atributo y configurarlo durante el onChange:

var Field = React.createClass({
      render: function () {
          // never renders new value...
          return (
              <div>
                  <input type="text" defaultValue={this.props.default || ''} value={this.props.value} />
              </div>
          );
      }
  });

Aquí hay un plunker mostrando el cambio


4
2018-06-09 11:28



También me enfrento a este problema, lo que hice fue actualizar manualmente el valor de entrada cuando los accesorios han cambiado. Agregue esto a su clase de reacción de campo:

componentWillReceiveProps(nextProps){
    if(nextProps.value != this.props.value) {
        document.getElementById(<element_id>).value = nextProps.value
    }
}

Solo necesita agregar un atributo de identificación a su elemento para que pueda ubicarse.


0
2017-08-09 05:44



El problema está aquí:

onClick={this.changeTo.bind(null, 'Whyyyy?')}

Tengo curiosidad de por qué te unes a null.

Desea enlazar a 'esto', de modo que changeTo establecerá State en ESTE objeto.

Prueba esto

<button onClick={this.changeTo.bind(this, 'Whyyyy?')}>Change to "Whyyyy?"</button>
<button onClick={this.changeTo.bind(this, void 0)}>Change to undefined</button>

En Javascript, cuando se llama a una función, se invoca en el ámbito desde el que se invocó, no donde se escribió (lo sé, parece contrario a la intuición). Para asegurarse de que se invoca en el contexto en que lo escribe, debe '' bind (this) ''.

Para obtener más información sobre el ámbito de la vinculación y la función, hay muchos cursos en línea (algunos mucho mejores que otros). Puede que le guste este: http://ryanmorr.com/understanding-scope-and-context-in-javascript/

También recomiendo usar las herramientas React Dev si estás usando Firefox o Chrome, de esta manera hubieras podido ver ese estado. El mensaje no estaba cambiando: https://facebook.github.io/react/blog/2015/09/02/new-react-developer-tools.html


0
2017-09-27 03:18



Use el renderizado condicional, luego el componente cargará el valor inicial correcto. Algo como en este módulo:

class MenuHeaderInput extends React.Component{
    constructor(props){
        super(props);
        this.handleBlur = this.handleBlur.bind (this);
    }
    handleBlur (e) {
        this.props.menuHeaderUpdate(e.target.value);
    }
    render(){
        if (this.props.menuHeader) {
            return (
                <div className="w3-row w3-margin" onClick = {() => this.props.handleTitleClick (10)}>
                    <div className="w3-third" ><pre></pre></div>
                    <input
                        className = {"w3-third w3-input w3-jumbo " + EDIT_COLOR}                
                        type = "text"
                        defaultValue = {this.props.menuHeader}
                        onBlur = {this.handleBlur}
                    />
                    <div className="w3-third" ><pre></pre></div>                
                </div>
            )
        }
        else {
            return null;
        }
    }
}

0
2018-04-13 13:54



Puede hacer la entrada condicionalmente y luego cada vez que quiera forzar una actualización del defaultValue solo necesitas desmontar la entrada y luego volver a renderizarla de inmediato.


0
2018-05-23 14:33