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>
    );
  }
});
jdarling
fuente
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
zbyte
fuente
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.

Lin
fuente
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.

akiespenc
fuente
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,
      },
    });
  }}
/>
spencer.sm
fuente
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;
    }
Pawel Gorczynski
fuente
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} />;
Tanner Burton
fuente
1

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

this.refs.complete.state.switched
Sakshi Nagpal
fuente