私は初めて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);
重要なのは、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>
<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>
これが三項演算子の代替構文です。
{ this.state.showMyComponent ? <MyComponent /> : null }
以下と同等です。
{ this.state.showMyComponent && <MyComponent /> }
display: 'none';
による代替構文
<MyComponent style={this.state.showMyComponent ? {} : { display: 'none' }} />
ただし、display: 'none'
を使いすぎると、DOMの汚染につながり、最終的にはアプリケーションの動作が遅くなります。
これが私の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
最新のバージョンでは0.11が反応しているので、コンテンツをレンダリングしないためにnullを返すこともできます。
https://facebook.github.io/react/blog/2014/07/13/react-v0.11-rc1.html#rendering-to-null
私はあなたのためにこれを処理する小さなコンポーネントを作成しました: 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);
あなたは状態にブール値を設定し(例えば 'show)'、そしてそれから:
var style = {};
if (!this.state.show) {
style.display = 'none'
}
return <div style={style}>...</div>
いくつかの素晴らしい答えが既にあります、しかし、私は彼らが非常によく説明されたと思いません、そして、与えられた方法のいくつかは人々をつまずかせるかもしれないいくつかの落とし穴を含みます。それで、私はこれをして賛否両論を説明するために3つの主な方法(それに加えて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つの利点は、非表示コンポーネントが選択されるまでまったく作成されないことです。そのため、非表示のコンポーネントによって最初のページ読み込みが遅れることはありません。また、切り替え時にステートフルコンポーネントをリセットする必要がある場合もあります。その場合、これがあなたの最良の選択です。
これで両方のコンポーネントが一度作成されます。コンポーネントが非表示になっている場合は、残りのレンダーコードを短絡します。目に見える支柱を使用して他の方法で他のロジックを短絡することもできます。 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関数にプレースホルダを返させます。それ以外の場合はデータをレンダリングします。そうすれば、ページは素早くロードされ、ロードされるたびにタブに入力されます。ロジックを親に移動し、結果を小道具として子にプッシュすることもできます。そうすれば、どのタブを最初にロードするかを優先させることができます。または結果をキャッシュして、コンポーネントが最初に表示されたときにのみロジックを実行します。
クラス隠蔽はおそらく実装するのが最も簡単です。前述のように、display:noneでCSSクラスを作成し、propに基づいてクラスを割り当てるだけです。欠点は、すべての非表示コンポーネントのコード全体が呼び出され、すべての非表示コンポーネントがDOMに添付されることです。 (Option 1は隠されたコンポーネントをまったく作成しません。そしてOption 2はコンポーネントが隠されたときに不要なコードをショートさせてDOMからコンポーネントを完全に削除します。)他の答えが私はそれに話すことができない。
これはすべてのアプリケーションに対して機能するわけではなく、コンポーネントを非表示にすることではないので話題から外れていますが、非表示よりもユースケースによっては良い解決策になるかもしれません。タブがあるとしましょう。 1つのReactコンポーネントを作成して、タブに表示される内容を変更するためだけに小道具を使用することが可能かもしれません。また、JSXを状態変数に保存し、プロップを使用してレンダリング機能に返すJSXを決定することもできます。 JSXを生成する必要がある場合は、それを実行して親にキャッシュし、正しいものをプロップとして送信します。または、子を生成して子の状態にキャッシュし、小道具を使用してアクティブな子を選択します。
これは仮想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;
}
フィドル ここ
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>
);
}
}
ドキュメントによると、ベストプラクティスは次のとおりです。
{this.state.showFooter && <Footer />}
状態が有効な場合にのみ要素をレンダリングします。
私はReactチームからのこの声明から始めます。
Reactでは、必要な動作をカプセル化した個別のコンポーネントを作成できます。その後、アプリケーションの状態に応じて、それらのうちのいくつかのみをレンダリングできます。
Reactの条件付きレンダリングはJavaScriptの条件と同じように機能します。 ifや条件演算子のようなJavaScript演算子を使用して現在の状態を表す要素を作成し、それらに一致するようにReactにUIを更新させます。
ボタンをクリックしたときに基本的にコンポーネントを表示する必要があります。2つの方法で、純粋なReactを使うかCSSを使うか、純粋なReactの方法を使うことができます。 hideResults
はtrue
と表示されていませんが、ボタンをクリックすると状態が変化し、hideResults
はfalse
と表示され、コンポーネントは新しい値条件で再びレンダリングされます。
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で条件付きレンダリングについてさらに研究したい場合は、 ここ を見てください。
コンポーネントの表示をこのフィドルでチェックアウトする方法を確認したい場合は、.
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'));
場合によっては、より高次のコンポーネントが役立つことがあります。
高次コンポーネントを作成します。
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 ... /> }
この無駄のない短い構文を使用します。
{ this.state.show && <MyCustomComponent /> }
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 間違っている場合は修正してください。:)
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>
);
}
}
これは次のようにしても達成できます(非常に簡単な方法)
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
}
);
}
あなたは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
}
}
この例では、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);
あなたがブートストラップ4を使うなら、あなたはそのように要素を隠すことができます
className={this.state.hideElement ? "invisible" : "visible"}
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);