web-dev-qa-db-ja.com

Reactで要素を表示または非表示にする

私は初めてReact.jsをいじっていますが、クリックイベントでページ上に何かを表示したり隠したりする方法を見つけることができません。私は他のライブラリをページにロードしていないので、Reactライブラリを使ったネイティブな方法を探しています。これが私のこれまでのところです。 clickイベントが発生したときにdivを表示したいのですが。

var Search= React.createClass({
    handleClick: function (event) {
        console.log(this.prop);
    },
    render: function () {
        return (
            <div className="date-range">
                <input type="submit" value="Search" onClick={this.handleClick} />
            </div>
        );
    }
});

var Results = React.createClass({
    render: function () {
        return (
            <div id="results" className="search-results">
                Some Results
            </div>
        );
    }
});

React.renderComponent(<Search /> , document.body);
381
user1725382

重要なのは、setStateを使用してクリックハンドラ内のコンポーネントの状態を更新することです。状態の変更が適用されると、新しい状態でrenderメソッドが再度呼び出されます。

var Search = React.createClass({
    getInitialState: function() {
        return { showResults: false };
    },
    onClick: function() {
        this.setState({ showResults: true });
    },
    render: function() {
        return (
            <div>
                <input type="submit" value="Search" onClick={this.onClick} />
                { this.state.showResults ? <Results /> : null }
            </div>
        );
    }
});

var Results = React.createClass({
    render: function() {
        return (
            <div id="results" className="search-results">
                Some Results
            </div>
        );
    }
});

ReactDOM.render( <Search /> , document.getElementById('container'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.2/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/15.6.2/react-dom.min.js"></script>

<div id="container">
  <!-- This element's contents will be replaced with your component. -->
</div>

JSFiddle

416
Douglas
<style type="text/css">
    .hidden { display:none; }
</style>
render: function() {
    return (
      <div className={this.props.shouldHide ? 'hidden' : ''}>
        This will be hidden if you set <tt>props.shouldHide</tt> 
        to something truthy.
      </div>
    );
}

// or in more modern JS and stateless react
const Example = props => <div className={props.shouldHide}/>Hello</div>
174
John Haugeland

これが三項演算子の代替構文です。

{ this.state.showMyComponent ? <MyComponent /> : null }

以下と同等です。

{ this.state.showMyComponent && <MyComponent /> }

無駄のない理由


display: 'none';による代替構文

<MyComponent style={this.state.showMyComponent ? {} : { display: 'none' }} />

ただし、display: 'none'を使いすぎると、DOMの汚染につながり、最終的にはアプリケーションの動作が遅くなります。

88
Lyubomir

これが私のES6を使ったアプローチです。受け入れられた答えは正しいのですが、それはかなり時代遅れです。

import React, { Component } from 'react';
// you should use ReactDOM.render instad of React.renderComponent
import ReactDOM from 'react-dom';

class ToggleBox extends Component {
  constructor(props) {
    super(props);
    this.state = {
      // toggle box is closed initially
      isOpened: false,
    };
    // http://egorsmirnov.me/2015/08/16/react-and-es6-part3.html
    this.toggleBox = this.toggleBox.bind(this);
  }

  toggleBox() {
    this.setState(oldState => ({ isOpened: !oldState.isOpened }));
  }

  render() {
    const { title, children } = this.props;
    const { isOpened } = this.state;
    return (
      <div className="box">
        <div className="boxTitle" onClick={this.toggleBox}>
          {title}
        </div>
        {isOpened && children && (
          <div className="boxContent">
            {children}
          </div>
        )}
      </div>
    );
  }
}

ReactDOM.render((
  <ToggleBox title="Click me">
    <div>Some content</div>
  </ToggleBox>
), document.getElementById('app'));

デモ: http://jsfiddle.net/kb3gN/16688/ /

display: noneを使用してCSSクラスを追加するよりも、必要な場合にのみ何らかの要素をレンダリングする方が適切です。 display: noneを設定した場合 - elementはまだreactによってレンダリングされ、DOMに追加されます - これはパフォーマンスに悪影響を及ぼす可能性があります。

タブ付きのページがあり、すべてのタブに多くのコンテンツがあり、一度に1つのタブしか開かれていないとします。表示されることになっている要素だけをDOMに保持するほうがはるかに良いです。

上記のコードでは、これを実現するために、次のようなコードを使用しています。

{opened && <SomeElement />}

SomeElementがtrueの場合のみ、それはopenedをレンダリングします。 JavaScriptが論理条件をどのように解決するかによって、うまくいきます。

true && true && 2; // will output 2
true && false && 2; // will output false
true && 'some string'; // will output 'some string'
opened && <SomeElement />; // will output SomeElement if `opened` is true, will output false otherwise
42
pie6k

最新のバージョンでは0.11が反応しているので、コンテンツをレンダリングしないためにnullを返すこともできます。

https://facebook.github.io/react/blog/2014/07/13/react-v0.11-rc1.html#rendering-to-null

15
squiddle

私はあなたのためにこれを処理する小さなコンポーネントを作成しました: https://www.npmjs.com/package/react-toggle-display

hideまたはshowプロップに基づいて、style属性をdisplay: none !importantに設定します。

使用例

var ToggleDisplay = require('react-toggle-display');

var Search = React.createClass({
    getInitialState: function() {
        return { showResults: false };
    },
    onClick: function() {
        this.setState({ showResults: true });
    },
    render: function() {
        return (
            <div>
                <input type="submit" value="Search" onClick={this.onClick} />
                <ToggleDisplay show={this.state.showResults}>
                    <Results />
                </ToggleDisplay>
            </div>
        );
    }
});

var Results = React.createClass({
    render: function() {
        return (
            <div id="results" className="search-results">
                Some Results
            </div>
        );
    }
});

React.renderComponent(<Search />, document.body);
10
ccnokes

あなたは状態にブール値を設定し(例えば 'show)'、そしてそれから:

var style = {};
if (!this.state.show) {
  style.display = 'none'
}

return <div style={style}>...</div>
8
FakeRainBrigand

いくつかの素晴らしい答えが既にあります、しかし、私は彼らが非常によく説明されたと思いません、そして、与えられた方法のいくつかは人々をつまずかせるかもしれないいくつかの落とし穴を含みます。それで、私はこれをして賛否両論を説明するために3つの主な方法(それに加えて1つのトピック外のオプション)を調べるつもりです。私は主にこれを書いています。なぜなら、オプション1が大いに推奨されていて、正しく使用されない場合、そのオプションには潜在的な問題がたくさんあるからです。

オプション1:親での条件付きレンダリング.

コンポーネントを1回だけレンダリングしてそこに残しておかない限り、この方法は好きではありません。問題は、可視性を切り替えるたびに、reactがスクラッチからコンポーネントを作成することです。これがその例です。 LogoutButtonまたはLoginButtonは、条件付きで親LoginControlにレンダリングされています。これを実行すると、コンストラクタがボタンをクリックするたびに呼び出されるようになります。 https://codepen.io/Kelnor/pen/LzPdpN?editors=1111

class LoginControl extends React.Component {
  constructor(props) {
    super(props);
    this.handleLoginClick = this.handleLoginClick.bind(this);
    this.handleLogoutClick = this.handleLogoutClick.bind(this);
    this.state = {isLoggedIn: false};
  }

  handleLoginClick() {
    this.setState({isLoggedIn: true});
  }

  handleLogoutClick() {
    this.setState({isLoggedIn: false});
  }

  render() {
    const isLoggedIn = this.state.isLoggedIn;

    let button = null;
    if (isLoggedIn) {
      button = <LogoutButton onClick={this.handleLogoutClick} />;
    } else {
      button = <LoginButton onClick={this.handleLoginClick} />;
    }

    return (
      <div>
        <Greeting isLoggedIn={isLoggedIn} />
        {button}
      </div>
    );
  }
}

class LogoutButton extends React.Component{
  constructor(props, context){
    super(props, context)
    console.log('created logout button');
  }
  render(){
    return (
      <button onClick={this.props.onClick}>
        Logout
      </button>
    );
  }
}

class LoginButton extends React.Component{
  constructor(props, context){
    super(props, context)
    console.log('created login button');
  }
  render(){
    return (
      <button onClick={this.props.onClick}>
        Login
      </button>
    );
  }
}

function UserGreeting(props) {
  return <h1>Welcome back!</h1>;
}

function GuestGreeting(props) {
  return <h1>Please sign up.</h1>;
}

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) {
    return <UserGreeting />;
  }
  return <GuestGreeting />;
}

ReactDOM.render(
  <LoginControl />,
  document.getElementById('root')
);

Reactはコンポーネントを一から作成するのがとても簡単です。ただし、作成時にコードを呼び出す必要があります。そのため、コンストラクタ、componentDidMount、renderなどのコードが高価な場合は、コンポーネントの表示が大幅に遅くなります。また、非表示時に状態を保持し(表示時に復元したい)、ステートフルコンポーネントでこれを使用することはできません。1つの利点は、非表示コンポーネントが選択されるまでまったく作成されないことです。そのため、非表示のコンポーネントによって最初のページ読み込みが遅れることはありません。また、切り替え時にステートフルコンポーネントをリセットする必要がある場合もあります。その場合、これがあなたの最良の選択です。

オプション2:子での条件付きレンダリング

これで両方のコンポーネントが一度作成されます。コンポーネントが非表示になっている場合は、残りのレンダーコードを短絡します。目に見える支柱を使用して他の方法で他のロジックを短絡することもできます。 codepenページのconsole.logに注目してください。 https://codepen.io/Kelnor/pen/YrKaWZ?editors=0011

class LoginControl extends React.Component {
  constructor(props) {
    super(props);
    this.handleLoginClick = this.handleLoginClick.bind(this);
    this.handleLogoutClick = this.handleLogoutClick.bind(this);
    this.state = {isLoggedIn: false};
  }

  handleLoginClick() {
    this.setState({isLoggedIn: true});
  }

  handleLogoutClick() {
    this.setState({isLoggedIn: false});
  }

  render() {
    const isLoggedIn = this.state.isLoggedIn;
    return (
      <div>
        <Greeting isLoggedIn={isLoggedIn} />
        <LoginButton isLoggedIn={isLoggedIn} onClick={this.handleLoginClick}/>
        <LogoutButton isLoggedIn={isLoggedIn} onClick={this.handleLogoutClick}/>
      </div>
    );
  }
}

class LogoutButton extends React.Component{
  constructor(props, context){
    super(props, context)
    console.log('created logout button');
  }
  render(){
    if(!this.props.isLoggedIn){
      return null;
    }
    return (
      <button onClick={this.props.onClick}>
        Logout
      </button>
    );
  }
}

class LoginButton extends React.Component{
  constructor(props, context){
    super(props, context)
    console.log('created login button');
  }
  render(){
    if(this.props.isLoggedIn){
      return null;
    }
    return (
      <button onClick={this.props.onClick}>
        Login
      </button>
    );
  }
}

function UserGreeting(props) {
  return <h1>Welcome back!</h1>;
}

function GuestGreeting(props) {
  return <h1>Please sign up.</h1>;
}

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) {
    return <UserGreeting />;
  }
  return <GuestGreeting />;
}

ReactDOM.render(
  <LoginControl />,
  document.getElementById('root')
);

今、初期化ロジックが速くて、子供たちがステートレスであるなら、あなたはパフォーマンスや機能の違いを見ることはないでしょう。しかし、どうしてもReactに、まったく新しいコンポーネントを作成させるのですか。ただし、初期化に時間がかかる場合は、コンポーネントを切り替えるたびにオプション1が実行され、切り替え時にページが遅くなります。オプション2では、最初のページの読み込み時にすべてのコンポーネントの初期化が実行されます。その最初の負荷を遅くします。もう一度注意してください。条件に基づいてコンポーネントを1回だけ表示して切り替えていない場合、または切り替え時にコンポーネントをリセットしたい場合は、オプション1が最適で、おそらく最善の選択肢です。

しかし、ページの読み込みが遅いことが問題になる場合は、ライフサイクルの方法で高価なコードを入手していることを意味します。一般的にはそれはお勧めできません。高価なコードをライフサイクルメソッドから除外することで、遅いページロードを解決することができます。それをComponentDidMountによって開始された非同期関数に移動し、コールバックでsetState()を使用してそれを状態変数に入れます。状態変数がnullで、コンポーネントが可視の場合は、render関数にプレースホルダを返させます。それ以外の場合はデータをレンダリングします。そうすれば、ページは素早くロードされ、ロードされるたびにタブに入力されます。ロジックを親に移動し、結果を小道具として子にプッシュすることもできます。そうすれば、どのタブを最初にロードするかを優先させることができます。または結果をキャッシュして、コンポーネントが最初に表示されたときにのみロジックを実行します。

オプション3:クラス隠蔽

クラス隠蔽はおそらく実装するのが最も簡単です。前述のように、display:noneでCSSクラスを作成し、propに基づいてクラスを割り当てるだけです。欠点は、すべての非表示コンポーネントのコード全体が呼び出され、すべての非表示コンポーネントがDOMに添付されることです。 (Option 1は隠されたコンポーネントをまったく作成しません。そしてOption 2はコンポーネントが隠されたときに不要なコードをショートさせてDOMからコンポーネントを完全に削除します。)他の答えが私はそれに話すことができない。

オプション4:1つのコンポーネントがプロップを変更します。あるいは、コンポーネントがまったくなく、HTMLをキャッシュすることもあります。

これはすべてのアプリケーションに対して機能するわけではなく、コンポーネントを非表示にすることではないので話題から外れていますが、非表示よりもユースケースによっては良い解決策になるかもしれません。タブがあるとしましょう。 1つのReactコンポーネントを作成して、タブに表示される内容を変更するためだけに小道具を使用することが可能かもしれません。また、JSXを状態変数に保存し、プロップを使用してレンダリング機能に返すJSXを決定することもできます。 JSXを生成する必要がある場合は、それを実行して親にキャッシュし、正しいものをプロップとして送信します。または、子を生成して子の状態にキャッシュし、小道具を使用してアクティブな子を選択します。

7
Kelnor

これは仮想DOMを利用するための良い方法です。

反応:

            var Comp = React.createClass({
                getInitialState: function(){
                return {hide: false};
              },
              toggle: function(){
                this.setState({hide: !this.state.hide});
              },
              render: function() {
                return <div>
                        <button onClick={this.toggle}>toggle</button>    
                    <div className={'hide-' + this.state.hide}>Hi there</div>
                </div>;
              }
            });

            ReactDOM.render(
              <Comp />,
              document.getElementById('container')
            );

CSS

            .hide-true  {
              display: none;
            }

フィドル ここ

5
daniloprates
   class FormPage extends React.Component{
      constructor(props){
           super(props);
           this.state = {
             hidediv: false
           }
      }

     handleClick = (){
       this.setState({
          hidediv: true
        });
      }

      render(){
        return(
        <div>
          <div className="date-range" hidden = {this.state.hidediv}>
               <input type="submit" value="Search" onClick={this.handleClick} />
          </div>
          <div id="results" className="search-results" hidden = {!this.state.hidediv}>
                        Some Results
           </div>
        </div>
        );
      }
  }
4
Akanksha gore

ドキュメントによると、ベストプラクティスは次のとおりです。

 {this.state.showFooter && <Footer />}

状態が有効な場合にのみ要素をレンダリングします。

3
Dynamic

私はReactチームからのこの声明から始めます。

Reactでは、必要な動作をカプセル化した個別のコンポーネントを作成できます。その後、アプリケーションの状態に応じて、それらのうちのいくつかのみをレンダリングできます。

Reactの条件付きレンダリングはJavaScriptの条件と同じように機能します。 ifや条件演算子のようなJavaScript演算子を使用して現在の状態を表す要素を作成し、それらに一致するようにReactにUIを更新させます。

ボタンをクリックしたときに基本的にコンポーネントを表示する必要があります。2つの方法で、純粋なReactを使うかCSSを使うか、純粋なReactの方法を使うことができます。 hideResultstrueと表示されていませんが、ボタンをクリックすると状態が変化し、hideResultsfalseと表示され、コンポーネントは新しい値条件で再びレンダリングされます。

var Search = React.createClass({
  getInitialState: function() {
    return { hideResults: true };
  },

  handleClick: function() {
    this.setState({ hideResults: false });
  },

  render: function() {
    return (
      <div>
        <input type="submit" value="Search" onClick={this.handleClick} />
        { !this.state.hideResults && <Results /> }
      </div> );
  }

});

var Results = React.createClass({
  render: function() {
    return (
    <div id="results" className="search-results">
      Some Results
    </div>);
   }
});

ReactDOM.render(<Search />, document.body);

Reactで条件付きレンダリングについてさらに研究したい場合は、 ここ を見てください。

3
Alireza

コンポーネントの表示をこのフィドルでチェックアウトする方法を確認したい場合は、.

http://jsfiddle.net/mnoster/kb3gN/16387/ /

var Search = React.createClass({
    getInitialState: function() {
        return { 
            shouldHide:false
        };
    },
    onClick: function() {
        console.log("onclick");
        if(!this.state.shouldHide){
            this.setState({
                shouldHide: true 
            })
        }else{
                    this.setState({
                shouldHide: false 
            })
        }
    },
render: function() {
    return (
      <div>
        <button onClick={this.onClick}>click me</button>
        <p className={this.state.shouldHide ? 'hidden' : ''} >yoyoyoyoyo</p>
      </div>
    );
}
});

ReactDOM.render( <Search /> , document.getElementById('container'));
3
Nicholas Porter

場合によっては、より高次のコンポーネントが役立つことがあります。

高次コンポーネントを作成します。

export var HidableComponent = (ComposedComponent) => class extends React.Component {
    render() {
        if ((this.props.shouldHide!=null && this.props.shouldHide()) || this.props.hidden)
            return null;
        return <ComposedComponent {...this.props}  />;
    }
};

あなた自身のコンポーネントを拡張する:

export const MyComp= HidableComponent(MyCompBasic);

それからあなたはこのようにそれを使うことができます:

<MyComp hidden={true} ... />
<MyComp shouldHide={this.props.useSomeFunctionHere} ... />

これにより、ちょっとした定型句が少なくなり、命名規則に従うことが強制されますが、MyCompはまだインスタンス化されることに注意してください。省略する方法は前述したとおりです。

{ !hidden && <MyComp ... /> }

2
vinga

この無駄のない短い構文を使用します。

{ this.state.show && <MyCustomComponent /> }
1
Zain Ul Hassan

refを使用してCSSを操作する

1つの方法は、Reactのrefを使用し、ブラウザーのAPIを使用してCSSクラスを操作することです。唯一の目的がボタンのクリックで一部のDOM要素を非表示/表示することである場合、その利点はReactでの再レンダリングを回避することです。

// Parent.jsx
import React, { Component } from 'react'

export default class Parent extends Component {
    constructor () {    
        this.childContainer = React.createRef()
    }

    toggleChild = () => {
        this.childContainer.current.classList.toggle('hidden')
    }

    render () {
        return (
            ...

            <button onClick={this.toggleChild}>Toggle Child</button>
            <div ref={this.childContainer}>
                <SomeChildComponent/>
            </div>

            ...
        );
    }
}


// styles.css
.hidden {
    display: none;
}

PS 間違っている場合は修正してください。:)

1

rc-if-else moduleを使用

npm install --save rc-if-else
import React from 'react';
import { If } from 'rc-if-else';

class App extends React.Component {
    render() {
        return (
            <If condition={this.props.showResult}>
                Some Results
            </If>
        );
    }
}
1
qinyuanbin

これは次のようにしても達成できます(非常に簡単な方法)

 class app extends Component {
   state = {
     show: false
   };
 toggle= () => {
   var res = this.state.show;
   this.setState({ show: !res });
 };
render() {
  return(
   <button onClick={ this.toggle }> Toggle </button>
  {
    this.state.show ? (<div> HELLO </div>) : null
  }
   );
     }
1
basitmir

あなたはCSSファイルを使用することができます

    var Results = React.createClass({
    render: function() {
        return (
            <div id="results" className={`search-results ${this.state.showResults ? 'show' : ''}`}>
                Some Results
            </div>
        );
    }
})

そしてcssファイルで

    .search-results {
     ...
     display: none
     &.show {
      display: block
   }
}
0
arco

この例では、1秒ごとに切り替わるトグルを使用してコンポーネントを切り替える方法を示します。

import React ,{Fragment,Component} from "react";
import ReactDOM from "react-dom";

import "./styles.css";

const Component1 = () =>(
  <div>
    <img 
src="https://i.pinimg.com/originals/58/df/1d/58df1d8bf372ade04781b8d4b2549ee6.jpg" />
   </div>
)

const Component2 = () => {
  return (
    <div>
       <img 
src="http://www.chinabuddhismencyclopedia.com/en/images/thumb/2/2e/12ccse.jpg/250px- 
12ccse.jpg" />
  </div>
   )

 }

 class App extends Component {
   constructor(props) {
     super(props);
    this.state = { 
      toggleFlag:false
     }
   }
   timer=()=> {
    this.setState({toggleFlag:!this.state.toggleFlag})
  }
  componentDidMount() {
    setInterval(this.timer, 1000);
   }
  render(){
     let { toggleFlag} = this.state
    return (
      <Fragment>
        {toggleFlag ? <Component1 /> : <Component2 />}
       </Fragment>
    )
  }
}


const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
0
Snivio

あなたがブートストラップ4を使うなら、あなたはそのように要素を隠すことができます

className={this.state.hideElement ? "invisible" : "visible"}
0
ThomasP1988
var Search= React.createClass({
 getInitialState: () => { showResults: false },
 onClick: () => this.setState({ showResults: true }),
 render: function () {
   const { showResults } = this.state;
   return (
     <div className="date-range">
       <input type="submit" value="Search" onClick={this.handleClick} />
       {showResults && <Results />}
     </div>
   );
 }
});

var Results = React.createClass({
    render: function () {
        return (
            <div id="results" className="search-results">
                Some Results
            </div>
        );
    }
});

React.renderComponent(<Search /> , document.body);
0