Come attivare lo stato booleano del componente React?


90

Mi piacerebbe sapere come attivare uno stato booleano di un componente di reazione. Per esempio:

Ho il controllo dello stato booleano nel costruttore del mio componente:

constructor(props, context) { 
   super(props, context);

   this.state = {
      check: false
   };
};

Sto provando a cambiare lo stato ogni volta che si fa clic sulla mia casella di controllo, utilizzando il metodo this.setState:

<label><input type=checkbox" value="check" onChange = {(e) => this.setState({check: !check.value})}/> Checkbox </label>

Ovviamente ottengo un errore di riferimento non rilevato: il controllo non è definito . Allora come posso ottenerlo?

Molte grazie in anticipo.


3
È esattamente come dice, l'assegno non è definito. Probabilmente dire di scrivere this.state.checkin this.setState({check: !check.value}). E aggiungi la proprietà selezionata per la casella di controllo, che cambierà in base allo stato del componente. checked={this.state.checked}
Vincas Stonys

Risposte:


260

Dato che nessuno ha pubblicato questo messaggio, sto postando la risposta corretta. Se il tuo nuovo aggiornamento di stato dipende dallo stato precedente, usa sempre la forma funzionale setStateche accetta come argomento una funzione che restituisce un nuovo stato.

Nel tuo caso:

this.setState(prevState => ({
  check: !prevState.check
}));

Vedi i documenti


Poiché questa risposta sta diventando popolare, aggiungendo l'approccio che dovrebbe essere usato per React Hooks (v16.8 +):

Se stai usando l' useStatehook, usa il seguente codice (nel caso il tuo nuovo stato dipenda dallo stato precedente):

const [check, setCheck] = useState(false);
// ...
setCheck(prevCheck => prevCheck + 1);

4
perché è meglio dell'utilizzo diretto this.setState({check: !this.state.check})?
SunnyPro

11
@SunnyPro Leggi i documenti collegati e troverai la tua risposta. TL; DR è reattivo ottimizza le chiamate per impostare lo stato raggruppandole insieme. Quindi immagina una semplice funzione di incremento increment = () => this.setState({count: this.state.count + 1});e un blocco di codice: increment(); increment(); increment();ora reagire può raggrupparli in qualcosa di analogo a: setNewState = (oldState) => { newState.count = oldState.count + 1; newState.count = oldState.count + 1; newState.count = oldState.count + 1; return newState; } vedi dove si trova il problema?
Drew Reese

cosa succede se ho bisogno di aggiornare altre proprietà di stato che non dipendono dallo stato precedente allo stesso? Ad esempio, attivare un messaggio popover, con visibile come vero / falso ma il messaggio cambia a seconda dello stato?
hamncheez

1
@hamncheez Il valore di ritorno della funzione è comunque il tuo nuovo stato. È possibile o meno utilizzare i valori dello stato precedente; in modo da poter inviare qualsiasi valore, come messaggi diversi.
Dane

16

Dovresti usare this.state.checkinvece di check.valuequi:

this.setState({check: !this.state.check})

Ma comunque è una cattiva pratica farlo in questo modo. Molto meglio spostarlo in un metodo separato e non scrivere callback direttamente nel markup.


Voto positivo, ma per curiosità: perché questa "cattiva pratica"?
Fellow Stranger

2
Questa non è solo una cattiva pratica, ma potresti non ottenere il risultato desiderato, poiché setStateè asincrono . Vedi la mia risposta di seguito.
Dane

1
Penso che la risposta di Dane abbia un approccio migliore poiché utilizza l'API di React pensata per essere utilizzata nel caso in cui il nuovo stato dipenda dallo stato precedente.
MT.

3
@MT. Ma poi, ho risposto anni dopo. C'è quello :)
Dane

1
Poiché this.state è asincrono, non dovresti mai fare affidamento sul suo valore per aggiornare lo stato successivo. Usa invece una funzione di callback come suggerito da @Dane.
Dr. Younes Henni

5

Utilizzare checkedper ottenere il valore. Durante onChange, checkedsarà truee sarà una specie di boolean.

Spero che sia di aiuto!

class A extends React.Component {
  constructor() {
    super()
    this.handleCheckBox = this.handleCheckBox.bind(this)
    this.state = {
      checked: false
    }
  }
  
  handleCheckBox(e) {
    this.setState({
      checked: e.target.checked
    })
  }
  
  render(){
    return <input type="checkbox" onChange={this.handleCheckBox} checked={this.state.checked} />
  }
}

ReactDOM.render(<A/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>


4

Ecco un esempio che utilizza gli hook (richiede React> = 16.8.0)

// import React, { useState } from 'react';
const { useState } = React;

function App() {
  const [checked, setChecked] = useState(false);
  const toggleChecked = () => setChecked(value => !value);
  return (
    <input
      type="checkbox"
      checked={checked}
      onChange={toggleChecked}
    />
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"><div>


3

Puoi anche usare l' useStatehook di React per dichiarare lo stato locale di un componente funzione. Lo stato iniziale della variabile toggledè stato passato come argomento al metodo .useState.

import { render } from 'react-dom';
import React from "react";

type Props = {
  text: string,
  onClick(event: React.MouseEvent<HTMLButtonElement>): void,
};

export function HelloWorldButton(props: Props) {
  const [toggled, setToggled] = React.useState(false); // returns a stateful value, and a function to update it
  return <button
  onClick={(event) => {
    setToggled(!toggled);
    props.onClick(event);
  }}
  >{props.text} (toggled: {toggled.toString()})</button>;
}


render(<HelloWorldButton text='Hello World' onClick={() => console.log('clicked!')} />, document.getElementById('root'));

https://stackblitz.com/edit/react-ts-qga3vc


2

Provare:

<label><input type=checkbox" value="check" onChange = {(e) => this.setState({check: !this.state.check.value})}/> Checkbox </label>

Utilizzando check: !check.valuesignifica che sta cercando il filecheck oggetto, che non hai dichiarato.

È necessario specificare che si desidera il valore opposto di this.state.check.


2

Ho trovato questo il più semplice quando si attivano i valori booleani. In poche parole, se il valore è già vero, lo imposta su falso e viceversa. Fai attenzione agli errori indefiniti, assicurati che la tua proprietà sia stata definita prima dell'esecuzione

this.setState({
   propertyName: this.propertyName = !this.propertyName
});

1

A seconda del contesto; questo ti permetterà di aggiornare lo stato data la funzione mouseEnter. In entrambi i casi, impostando un valore di stato su true: false puoi aggiornare quel valore di stato data qualsiasi funzione impostandolo sul valore opposto con!this.state.variable

state = {
  hover: false
}

onMouseEnter = () => {
  this.setState({
    hover: !this.state.hover
  });
};

0

Sono stato atterrato in questa pagina quando cerco di utilizzare lo stato di commutazione nel componente React usando Redux ma non trovo qui alcun approccio che utilizzi lo stesso.

Quindi, penso che potrebbe aiutare qualcuno che stava lottando per implementare lo stato di commutazione usando Redux.

Il mio file del riduttore va qui. Ottengo lo stato iniziale false per impostazione predefinita.

const INITIAL_STATE = { popup: false };
export default (state = INITIAL_STATE, action) => {
    switch (action.type) {
        case "POPUP":
            return {
                ...state,
                popup: action.value
            };
        default:
            return state;
    }
    return state;
};

Cambio stato cliccando sull'immagine. Quindi, il mio tag img va qui con la funzione onClick.

<img onClick={togglePopup} src={props.currentUser.image} className="avatar-image avatar-image--icon" />

La mia funzione Toggle Popup va sotto, che chiama Dispatcher.

const togglePopup = ev => {
    ev.preventDefault();
    props.handlePopup(!props.popup);
};

Questa chiamata va alla funzione mapDispatchToProps sottostante che riflette lo stato commutato.

const mapDispatchToProps = dispatch => ({
    handlePopup: value => dispatch({ type: "POPUP", value })
});

Grazie.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.