Làm thế nào để chuyển đổi trạng thái boolean của thành phần phản ứng?


85

Tôi muốn biết cách chuyển đổi trạng thái boolean của một thành phần phản ứng. Ví dụ:

Tôi đã kiểm tra trạng thái boolean trong hàm tạo của thành phần của mình:

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

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

Tôi đang cố gắng chuyển đổi trạng thái mỗi khi hộp kiểm của tôi được nhấp, sử dụng phương thức this.setState:

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

Tất nhiên tôi nhận được Lỗi Tham chiếu Không có: Kiểm tra không được xác định . Vậy làm thế nào tôi có thể đạt được điều này?

Rất cám ơn trước.


3
Nó chính xác như nó nói, kiểm tra là không xác định. Bạn có thể có nghĩa là để viết this.state.checktrong this.setState({check: !check.value}). Và thêm thuộc tính đã chọn cho hộp kiểm, hộp kiểm này sẽ thay đổi theo trạng thái thành phần. checked={this.state.checked}
Vincas Stonys

Câu trả lời:


247

Vì không ai đăng bài này, tôi đăng câu trả lời chính xác. Nếu cập nhật trạng thái mới của bạn phụ thuộc vào trạng thái trước đó, hãy luôn sử dụng dạng hàm setStatemà trong đó nó chấp nhận làm đối số, một hàm trả về trạng thái mới.

Trong trường hợp của bạn:

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

Xem tài liệu


Vì câu trả lời này đang trở nên phổ biến, nên thêm phương pháp sẽ được sử dụng cho React Hooks (v16.8 +):

Nếu bạn đang sử dụng useStatehook, hãy sử dụng mã sau (trong trường hợp trạng thái mới của bạn phụ thuộc vào trạng thái trước đó):

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

4
tại sao điều này tốt hơn là sử dụng trực tiếp this.setState({check: !this.state.check})?
SunnyPro

10
@SunnyPro Đọc các tài liệu được liên kết và bạn sẽ tìm thấy câu trả lời cho mình. TL; DR là phản ứng tối ưu hóa các cuộc gọi để thiết lập trạng thái bằng cách nhóm chúng lại với nhau. Vì vậy, hãy tưởng tượng một hàm gia tăng đơn giản increment = () => this.setState({count: this.state.count + 1});và một khối mã: increment(); increment(); increment();Bây giờ react có thể gộp chúng thành một thứ tương tự như: setNewState = (oldState) => { newState.count = oldState.count + 1; newState.count = oldState.count + 1; newState.count = oldState.count + 1; return newState; } Xem vấn đề nằm ở đâu?
Drew Reese

Điều gì sẽ xảy ra nếu tôi cần cập nhật các thuộc tính trạng thái khác không phụ thuộc vào trạng thái trước đó? Ví dụ, ghi vào một thông báo popover, hiển thị là true / false nhưng thông báo thay đổi tùy theo trạng thái?
hamncheez

1
@hamncheez Dù sao thì giá trị trả về của hàm cũng là trạng thái mới của bạn. Bạn có thể hoặc không thể sử dụng các giá trị từ trạng thái trước đó; để bạn có thể gửi bất kỳ giá trị nào, chẳng hạn như các tin nhắn khác nhau.
Dane

17

Bạn nên sử dụng this.state.checkthay vì check.valueở đây:

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

Nhưng dù sao thì việc làm theo cách này là không tốt . Tốt hơn nhiều nên chuyển nó sang phương thức riêng biệt và không viết lệnh gọi lại trực tiếp trong đánh dấu.


Được ủng hộ, nhưng vì tò mò - tại sao điều này lại "thực hành xấu"?
Fellow Stranger

Tốt hơn nên tách riêng chế độ xem và logic vì bằng cách này bạn sẽ có thể xem và cập nhật logic cũng như đánh dấu của mình một cách riêng biệt và dễ dàng hơn.
Eugene Tsakh,

2
Đây không chỉ là thói quen xấu, nhưng bạn có thể không nhận được kết quả mong muốn, như setStatelà async . Xem câu trả lời của tôi dưới đây.
Dane

1
Tôi nghĩ câu trả lời của Dane có cách tiếp cận tốt hơn vì nó sử dụng API của React được sử dụng trong trường hợp trạng thái mới phụ thuộc vào trạng thái trước đó.
MT.

3
@MT. Nhưng rồi, nhiều năm sau tôi mới trả lời. Có đó :)
Dane

5

Sử dụng checkedđể nhận giá trị. Trong onChange, checkedsẽ được truevà nó sẽ là một loại boolean.

Hi vọng điêu nay co ich!

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

Đây là một ví dụ sử dụng hook (yêu cầu 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

Bạn cũng có thể sử dụng useStatehook của React để khai báo trạng thái cục bộ cho một thành phần hàm. Trạng thái ban đầu của biến toggledđã được chuyển làm đối số cho phương thức .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

Thử:

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

Sử dụng check: !check.valuecó nghĩa là nó đang tìm kiếm checkđối tượng mà bạn chưa khai báo.

Bạn cần xác định rằng bạn muốn giá trị đối lập của this.state.check.


2

Tôi thấy điều này đơn giản nhất khi chuyển đổi các giá trị boolean. Nói một cách đơn giản nếu giá trị đã là true thì nó sẽ đặt nó thành false và ngược lại. Cẩn thận với các lỗi không xác định, đảm bảo thuộc tính của bạn đã được xác định trước khi thực thi

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

! Cám ơn vì cái này. Nó đã làm việc cho tôi.
Mo1

2

Tùy thuộc vào ngữ cảnh của bạn; điều này sẽ cho phép bạn cập nhật trạng thái cho hàm mouseEnter. Dù bằng cách nào, bằng cách đặt giá trị trạng thái thành true: false, bạn có thể cập nhật giá trị trạng thái đó cho bất kỳ hàm nào bằng cách đặt nó thành giá trị đối lập với!this.state.variable

state = {
  hover: false
}

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

0

Tôi đã được đưa vào trang này khi tôi đang tìm kiếm để sử dụng trạng thái chuyển đổi trong thành phần React bằng Redux nhưng tôi không tìm thấy ở đây bất kỳ cách tiếp cận nào bằng cách sử dụng tương tự.

Vì vậy, tôi nghĩ nó có thể giúp ích cho những người đang gặp khó khăn trong việc triển khai trạng thái chuyển đổi bằng cách sử dụng Redux.

Tệp giảm tốc của tôi ở đây. Tôi nhận được trạng thái ban đầu là sai theo mặc định.

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

Tôi thay đổi trạng thái khi nhấp vào hình ảnh. Vì vậy, thẻ img của tôi ở đây với chức năng onClick.

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

Hàm Toggle Popup của tôi ở bên dưới, gọi là Dispatcher.

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

Lệnh gọi này đi đến hàm mapDispatchToProps bên dưới, nó phản ánh lại trạng thái được bật.

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

Cảm ơn bạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.