Wie schalte ich den booleschen Zustand der Reaktionskomponente um?

86

Ich möchte wissen, wie man einen booleschen Zustand einer Reaktionskomponente umschaltet. Zum Beispiel:

Ich habe eine boolesche Statusprüfung im Konstruktor meiner Komponente:

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

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

Ich versuche, den Status jedes Mal umzuschalten, wenn auf mein Kontrollkästchen geklickt wird. Verwenden Sie dazu die Methode this.setState:

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

Natürlich bekomme ich einen Uncaught ReferenceError: check ist nicht definiert . Wie kann ich das erreichen?

Vielen Dank im Voraus.

Anfänger
quelle
3
Es ist genau so, wie es heißt, Scheck ist undefiniert. Sie haben wahrscheinlich gedacht , schreiben this.state.checkin this.setState({check: !check.value}). Fügen Sie die für das Kontrollkästchen aktivierte Eigenschaft hinzu, die sich je nach Komponentenstatus ändern würde. checked={this.state.checked}
Vincas Stonys

Antworten:

247

Da dies niemand gepostet hat, poste ich die richtige Antwort. Wenn Ihre neue Statusaktualisierung vom vorherigen Status abhängt, verwenden Sie immer die Funktionsform, setStatedie als Argument eine Funktion akzeptiert, die einen neuen Status zurückgibt.

In deinem Fall:

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

Siehe Dokumente


Da diese Antwort immer beliebter wird, fügen Sie den Ansatz hinzu, der für React Hooks (Version 16.8 +) verwendet werden sollte:

Wenn Sie den useStateHook verwenden, verwenden Sie den folgenden Code (falls Ihr neuer Status vom vorherigen Status abhängt):

const [check, setCheck] = useState(false);
// ...
setCheck(prevCheck => prevCheck + 1);
Däne
quelle
4
Warum ist das besser als direkt zu verwenden this.setState({check: !this.state.check})?
SunnyPro
10
@SunnyPro Lesen Sie die verlinkten Dokumente und Sie werden Ihre Antwort finden. Die Reaktion von TL; DR optimiert Anrufe, um den Status festzulegen, indem sie zusammen gestapelt werden. Stellen Sie sich also eine einfache Inkrementfunktion increment = () => this.setState({count: this.state.count + 1});und einen Codeblock vor: increment(); increment(); increment();Reagieren Sie jetzt und stapeln Sie diese in etwas Analoges zu: setNewState = (oldState) => { newState.count = oldState.count + 1; newState.count = oldState.count + 1; newState.count = oldState.count + 1; return newState; } Sehen Sie, wo das Problem liegt?
Drew Reese
Was ist, wenn ich andere Statuseigenschaften aktualisieren muss, die nicht gleichzeitig vom vorherigen Status abhängig sind? Zum Beispiel eine Popover-Nachricht umschalten, wobei sichtbar als wahr / falsch angezeigt wird, sich die Nachricht jedoch je nach Status ändert?
Hamncheez
1
@hamncheez Der Rückgabewert der Funktion ist sowieso Ihr neuer Status. Sie können Werte aus dem vorherigen Status verwenden oder nicht. So können Sie beliebige Werte wie verschiedene Nachrichten senden.
Däne
17

Sie sollten this.state.checkanstelle von check.valuehier verwenden:

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

Trotzdem ist es eine schlechte Praxis , dies so zu tun. Es ist viel besser, es in eine separate Methode zu verschieben und Rückrufe nicht direkt in das Markup zu schreiben.

Eugene Tsakh
quelle
Upvoted, aber aus Neugier - warum ist das "schlechte Praxis"?
Fellow Stranger
Es ist besser, Ansicht und Logik zu trennen, da Sie auf diese Weise Ihre Logik und Ihr Markup separat und einfacher anzeigen und aktualisieren können.
Eugene Tsakh
2
Dies ist nicht nur eine schlechte Übung, sondern Sie erhalten möglicherweise nicht das gewünschte Ergebnis, ebenso setStatewie Async . Siehe meine Antwort unten.
Däne
1
Ich denke, Danes Antwort hat einen besseren Ansatz, da sie die React-API verwendet, die für den Fall verwendet werden soll, dass der neue Status vom vorherigen Status abhängt.
MT.
3
@MT. Aber dann antwortete ich Jahre später. Da ist das :)
Däne
5

Verwenden Sie checked, um den Wert zu erhalten. Während onChange, checkedwird trueund es wird eine Art von sein boolean.

Hoffe das hilft!

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>

Pranesh Ravi
quelle
4

Hier ist ein Beispiel mit Hooks (erfordert 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>

Paolo Moretti
quelle
3

Sie können auch den useStateHook von React verwenden, um den lokalen Status für eine Funktionskomponente zu deklarieren. Der Anfangszustand der Variablen toggledwurde als Argument an die Methode übergeben .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

Yannic Hamann
quelle
2

Versuchen:

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

Verwenden check: !check.valuebedeutet, dass nach dem checkObjekt gesucht wird, das Sie nicht deklariert haben.

Sie müssen angeben, dass Sie den entgegengesetzten Wert von möchten this.state.check.

Dan Andersson
quelle
2

Ich fand dies am einfachsten, wenn ich boolesche Werte umschaltete. Einfach ausgedrückt, wenn der Wert bereits wahr ist, wird er auf falsch gesetzt und umgekehrt. Achten Sie auf undefinierte Fehler und stellen Sie sicher, dass Ihre Eigenschaft definiert wurde, bevor Sie sie ausführen

this.setState({
   propertyName: this.propertyName = !this.propertyName
});
rychrist88
quelle
! Danke dafür. Es hat bei mir funktioniert.
Mo1
2

Abhängig von Ihrem Kontext; Auf diese Weise können Sie den Status mit der mouseEnter-Funktion aktualisieren. In beiden Fällen können Sie diesen Statuswert für jede Funktion aktualisieren, indem Sie ihn auf den entgegengesetzten Wert mit setzen, indem Sie einen Statuswert auf true: false setzen!this.state.variable

state = {
  hover: false
}

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

Ich bin auf dieser Seite gelandet, als ich versucht habe, den Umschaltstatus in der React-Komponente mit Redux zu verwenden, aber ich finde hier keinen Ansatz, der denselben verwendet.

Ich denke, es könnte jemandem helfen, der Schwierigkeiten hatte, den Umschaltstatus mithilfe von Redux zu implementieren.

Meine Reduzierungsdatei geht hier. Ich erhalte standardmäßig den Anfangszustand false .

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

Ich ändere den Status beim Klicken auf das Bild. Also, mein img-Tag geht hier mit der onClick-Funktion.

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

Meine Popup-Funktion zum Umschalten wird unten angezeigt, die den Dispatcher aufruft.

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

Dieser Aufruf wird an die Funktion mapDispatchToProps weitergeleitet, die den umgeschalteten Status widerspiegelt.

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

Vielen Dank.

Balasubramani M.
quelle