如何切换反应组件的布尔状态?


85

我想知道如何切换React组件的布尔状态。例如:

我在组件的构造函数中进行了布尔状态检查:

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

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

我试图每次使用this.setState方法切换复选框时的状态:

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

当然,我得到了Uncaught ReferenceError:未定义检查。那么我该如何实现呢?

提前谢谢了。


3
确切地说,检查是未定义的。你大概的意思是写this.state.checkthis.setState({check: !check.value})。并添加已选中复选框的属性,该属性会根据组件状态而变化。checked={this.state.checked}
Vincas Stonys's

Answers:


247

由于没有人发布此消息,因此我发布了正确的答案。如果您的新状态更新依赖于先前的状态,请始终使用其函数形式setState接受返回新状态的函数作为参数。

在您的情况下:

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

查看文件


由于此答案越来越流行,因此添加了应用于React Hooks(v16.8 +)的方法:

如果使用useState挂钩,请使用以下代码(以防新状态取决于先前状态):

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

4
为什么比直接使用更好this.setState({check: !this.state.check})
SunnyPro

10
@SunnyPro阅读链接的文档,您将找到答案。TL; DR是通过将呼叫批处理在一起来优化呼叫以设置状态的。因此,请想象一个简单的增量函数increment = () => this.setState({count: this.state.count + 1});和一个代码块:increment(); increment(); increment();现在,react可以将它们批处理成类似于以下内容的代码:setNewState = (oldState) => { newState.count = oldState.count + 1; newState.count = oldState.count + 1; newState.count = oldState.count + 1; return newState; } 看看问题出在哪里?
德鲁·里斯

如果我需要更新其他不依赖于先前状态的状态属性怎么办?例如,切换一条显示为true / false的popover消息,但是该消息根据状态而变化?
hamncheez

1
@hamncheez函数的返回值仍然是您的新状态。您可能会或可能不会使用先前状态的值;因此您可以发送任何值,例如不同的消息。
丹妮

17

您应该使用this.state.check而不是check.value这里:

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

但是无论如何,这样做是一种不好的做法。最好将其移动到单独的方法,并且不要直接在标记中编写回调。


受到支持,但出于好奇-为什么这种“不良做法”?
陌生人研究员

最好将视图和逻辑分开,因为这样您将能够更轻松地分别查看和更新​​逻辑和标记。
尤金·察克

2
这不仅是一种不好的做法,而且您可能无法获得预期的结果,就像setStateasync一样。请参阅下面的答案。
丹妮'18

1
我认为Dane的答案有更好的方法,因为它使用了React的API,以便在新状态依赖于先前状态的情况下使用。
MT。

3
@公吨。但是,几年后,我回答了。就是这样:)
Dane

5

使用checked来获取值。在期间onChangechecked将是true并且将是一种boolean

希望这可以帮助!

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

这是一个使用钩子的示例(需要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

您还可以使用React的useState钩子为函数组件声明局部状态。变量的初始状态toggled已作为参数传递给方法.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

尝试:

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

使用check: !check.value表示它正在寻找check尚未声明的对象。

您需要指定您想要相反的值this.state.check


2

当切换布尔值时,我发现这是最简单的。简单地说,如果该值已经为true,则将其设置为false,反之亦然。提防未定义的错误,请确保在执行之前定义了属性

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

!谢谢你 它为我工作。
Mo1

2

根据您的环境;给定mouseEnter函数,这将允许您更新状态。无论哪种方式,都可以通过将状态值设置为true:false来更新给定功能的状态值,方法是使用!this.state.variable

state = {
  hover: false
}

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

0

当我使用Redux搜索在React组件中使用切换状态时,我就进入了此页面,但在这里我找不到使用相同状态的任何方法。

因此,我认为这可能会帮助那些努力使用Redux实现切换状态的人。

我的减速器文件在这里。默认情况下,我将初始状态设置为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;
};

单击图像时更改状态。因此,我的img标签带有onClick函数。

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

我的Toggle Popup函数位于下面,该函数称为Dispatcher。

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

该调用转到mapDispatchToProps函数下面,该函数反映回切换状态。

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

谢谢。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.