La casilla de verificación Reaccionar no se envía en Cambiar


136

TLDR: use defaultChecked en lugar de marcado, trabajando jsbin .

Intentando configurar una casilla de verificación simple que tachará el texto de la etiqueta cuando esté marcada. Por alguna razón, handleChange no se dispara cuando uso el componente. ¿Alguien puede explicar lo que estoy haciendo mal?

var CrossoutCheckbox = React.createClass({
  getInitialState: function () {
    return {
        complete: (!!this.props.complete) || false
      };
  },
  handleChange: function(){
    console.log('handleChange', this.refs.complete.checked); // Never gets logged
    this.setState({
      complete: this.refs.complete.checked
    });
  },
  render: function(){
    var labelStyle={
      'text-decoration': this.state.complete?'line-through':''
    };
    return (
      <span>
        <label style={labelStyle}>
          <input
            type="checkbox"
            checked={this.state.complete}
            ref="complete"
            onChange={this.handleChange}
          />
          {this.props.text}
        </label>
      </span>
    );
  }
});

Uso:

React.renderComponent(CrossoutCheckbox({text: "Text Text", complete: false}), mountNode);

Solución:

El uso de check no permite que el valor subyacente cambie (aparentemente) y, por lo tanto, no llama al controlador onChange. Cambiar a defaultChecked parece solucionar esto:

var CrossoutCheckbox = React.createClass({
  getInitialState: function () {
    return {
        complete: (!!this.props.complete) || false
      };
  },
  handleChange: function(){
    this.setState({
      complete: !this.state.complete
    });
  },
  render: function(){
    var labelStyle={
      'text-decoration': this.state.complete?'line-through':''
    };
    return (
      <span>
        <label style={labelStyle}>
          <input
            type="checkbox"
            defaultChecked={this.state.complete}
            ref="complete"
            onChange={this.handleChange}
          />
          {this.props.text}
        </label>
      </span>
    );
  }
});

3
En primer lugar, ¿por qué no agregar un onChange que sea más this.setState({checked: !this.state.checked})fácil que tener que almacenar un valor? Luego, un operador ternario en el atributo verificado:checked={this.state.checked ? 'checked': null}
zackify

Así es como comenzó, pero nunca pareció actualizarse. Así que comencé a esponjarlo aquí y allá para depurar lo que no estaba siendo despedido. Lo ideal sería volver a la forma más simple cuando se complete :)
jdarling

Suponiendo que su mountNode es un nodo dom real, tendría que usarlo this.refs.complete.getDOMNode().checked. ver violín jsfiddle.net/d10xyqu1
trekforever

Sin embargo, solo puede usar el estado en lugar de obtener el nodo dom: jsfiddle.net/d10xyqu1/1 Funciona bien, debe haber escrito mal algo.
zackify

2
Ignorar el comentario TLDR - defaultChecked no siempre es la respuesta
Chris

Respuestas:


207

Para obtener el estado marcado de su casilla de verificación, la ruta sería:

this.refs.complete.state.checked

La alternativa es obtenerlo del evento pasado al handleChangemétodo:

event.target.checked

3
No se llama a handleChange, no importa si hace clic en la casilla de verificación o en la etiqueta, no se llama a
handleChange

13
Intente usar defaultChecked = {this.state.complete} en lugar de "marcado" en su entrada.
zbyte

Eso fue todo ... buscado por siempre mirando y hurgando. Actualizará la pregunta con una respuesta de trabajo completa en caso de que otros también se encuentren con esto.
jdarling

Pero por qué, teniendo el mismo problema pero se supone que debes usarlo checkedpara componentes controlados: /
Dominic

44
configuración checkedsignifica que el estado se administra fuera del componente. Cuando el usuario hace clic, no hay nada que llamar, handleChangeya que no se actualiza ningún estado. En su lugar, debería escuchar onClicky activar una actualización de estado allí.
zbyte

29

Es mejor no usar referencias en tales casos. Utilizar:

<input
    type="checkbox"
    checked={this.state.active}
    onClick={this.handleClick}
/>

Hay algunas opciones:

checked vs defaultChecked

El primero respondería tanto a los cambios de estado como a los clics. Este último ignoraría los cambios de estado.

onClick vs onChange

El primero siempre se activaría con clics. Este último no se activaría con clics si el checkedatributo está presente en el inputelemento.


10

En el escenario en el que NO le gustaría usar el controlador onChange en el DOM de entrada, puede usar la onClickpropiedad como alternativa. La defaultCheckedcondición puede dejar un estado fijo para v16 IINM.

 class CrossOutCheckbox extends Component {
      constructor(init){
          super(init);
          this.handleChange = this.handleChange.bind(this);
      }
      handleChange({target}){
          if (target.checked){
             target.removeAttribute('checked');
             target.parentNode.style.textDecoration = "";
          } else {
             target.setAttribute('checked', true);
             target.parentNode.style.textDecoration = "line-through";
          }
      }
      render(){
         return (
            <span>
              <label style={{textDecoration: this.props.complete?"line-through":""}}>
                 <input type="checkbox"
                        onClick={this.handleChange}
                        defaultChecked={this.props.complete}
                  />
              </label>
                {this.props.text}
            </span>
        )
    }
 }

Espero que esto ayude a alguien en el futuro.


10

Si tiene una handleChangefunción que se ve así:

handleChange = (e) => {
  this.setState({
    [e.target.name]: e.target.value,
  });
}

Puede crear una onChangefunción personalizada para que actúe como lo haría una entrada de texto:

<input
  type="checkbox"
  name="check"
  checked={this.state.check}
  onChange={(e) => {
    this.handleChange({
      target: {
        name: e.target.name,
        value: e.target.checked,
      },
    });
  }}
/>

no está handleChangeencendido inputdebería ser this.handleChange?
Ardhi

5

En caso de que alguien esté buscando un controlador de eventos universal, el siguiente código se puede usar más o menos (suponiendo que la propiedad de nombre esté establecida para cada entrada):

    this.handleInputChange = (e) => {
        item[e.target.name] = e.target.type === "checkbox" ? e.target.checked : e.target.value;
    }

2

onChange no llamará a handleChange en el móvil cuando usa defaultChecked. Como alternativa, puede usar onClick y onTouchEnd.

<input onClick={this.handleChange} onTouchEnd={this.handleChange} type="checkbox" defaultChecked={!!this.state.complete} />;

1

En el material ui, el estado de la casilla de verificación se puede recuperar como

this.refs.complete.state.switched
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.