反応コンポーネントのブール状態を切り替える方法は?


90

反応コンポーネントのブール状態を切り替える方法を知りたいのですが。例えば:

コンポーネントのコンストラクターにブール状態チェックがあります。

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.checkの中でthis.setState({check: !check.value})。そして、チェックボックスがオンになっているプロパティを追加します。これは、コンポーネントの状態に応じて変化します。checked={this.state.checked}
Vincas Stonys 2016年

回答:


260

誰も投稿していないので、正解を投稿しています。新しい状態の更新が前の状態に依存している場合は、常に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 2018年

11
@SunnyProリンクされたドキュメントを読むと、答えが見つかります。TL; DRは、呼び出しをバッチ処理することにより、呼び出しを最適化して状態を設定します。したがって、単純なインクリメント関数increment = () => this.setState({count: this.state.count + 1});とコードのブロックを想像してみてください。reactは、increment(); increment(); increment();これらを次のようなものにバッチ処理できsetNewState = (oldState) => { newState.count = oldState.count + 1; newState.count = oldState.count + 1; newState.count = oldState.count + 1; return newState; } ます。問題がどこにあるかを確認しますか?
ドリューリース

以前の状態に同時に依存しない他の状態プロパティを更新する必要がある場合はどうなりますか?たとえば、ポップオーバーメッセージをトギングし、true / falseとして表示されますが、メッセージは状態に応じて変化しますか?
hamncheez

1
@hamncheez関数の戻り値は、とにかく新しい状態です。以前の状態の値を使用する場合と使用しない場合があります。そのため、さまざまなメッセージなど、任意の値を送信できます。
デーン

16

ここのthis.state.check代わりに使用する必要がありcheck.valueます:

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

しかしとにかく、このようにするのは悪い習慣です。別のメソッドに移動し、マークアップで直接コールバックを記述しない方がはるかに優れています。


賛成ですが、好奇心から-なぜこれが「悪い習慣」なのですか?
仲間の見知らぬ人2017年

2
これは悪い習慣であるだけでなく、setStateasyncのように、望ましい結果が得られない場合があります。以下の私の答えを参照してください。
デーン

1
Daneの答えは、新しい状態が前の状態に依存する場合に使用することを目的としたReactのAPIを使用しているため、より良いアプローチだと思います。
MT。

3
@MT。しかし、その後、私は数年後に答えました。それがあります:)
デーン

1
this.stateは非同期であるため、次の状態を更新するためにその値に依存しないでください。@Daneが提案したように、代わりに関数コールバックを使用してください。
Younes Henni博士

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

1

あなたの文脈に応じて; これにより、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" />

私のTogglePopup関数は以下になり、Dispatcherを呼び出します。

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

この呼び出しは、切り替えられた状態を反映するmapDispatchToProps関数の下に移動します。

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

ありがとうございました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.