แสดงหรือซ่อนองค์ประกอบในการตอบสนอง


532

ฉันยุ่งกับ React.js เป็นครั้งแรกและไม่สามารถหาวิธีแสดงหรือซ่อนบางสิ่งบางอย่างบนหน้าเว็บผ่านเหตุการณ์การคลิก ฉันไม่ได้โหลดไลบรารี่อื่น ๆ ไปที่หน้าดังนั้นฉันกำลังมองหาวิธีดั้งเดิมในการใช้ไลบรารี่ React นี่คือสิ่งที่ฉันมี ฉันต้องการแสดง 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);

11
ความคิดเห็นที่ได้รับการยอมรับใช้เทคโนโลยีนวนิยายเพื่อทำสิ่งที่เทคโนโลยีที่มีอยู่ในระดับดั้งเดิมสามารถทำได้ง่ายขึ้นเร็วขึ้นและสามารถแบ่งปันได้กับภาษาและห้องสมุดอื่น ๆ การจัดการกับ CSS มาตรฐานนี้เป็นคำตอบที่ดีกว่า
John Haugeland

13
@JohnHaugeland คำตอบที่ดีที่สุดเมื่อใช้กรอบการทำงาน React คือคำตอบที่ได้รับการยอมรับทุกสไตล์ของ React ซึ่งมีฟังก์ชั่นการล้างข้อมูลซึ่งในบางกรณีคุณต้องทำ ไม่ใช่วิธีที่ดีที่จะมีส่วนประกอบซ่อนอยู่ในความมืด ถ้าคุณผสมสิ่งต่าง ๆ คุณจะไปพื้นเมืองทั้งหมดซึ่งเร็วกว่าสิ่งอื่นเสมอ
Claudiu Hojda

4
ไม่มันไม่ใช่ การใช้การตอบสนองเพื่อสร้าง CSS เป็นแนวคิดที่ไม่ดี
John Haugeland

8
นอกจากนี้คุณดูเหมือนจะพลาดจุดที่ฉันพูดไปอย่างสิ้นเชิงซึ่งใช้ CSS เพื่อซ่อนและแสดงองค์ประกอบแทนที่จะใช้ React เพื่อลบเนื้อหาออก คุณสามารถใช้ React เพื่อใช้ CSS เพื่อซ่อนและแสดงองค์ประกอบได้อย่างง่ายดาย: <div style = {{display: this.props.example}} />
John Haugeland

5
@ClaudiuHojda ที่มีส่วนประกอบซ่อนอยู่ในความมืดเป็นจริงการปฏิบัติที่ดีมากในบางกรณีฉันคิดว่าการตอบสนองการนำทางที่คุณต้องการลิงค์ไปยังคงอยู่ใน HTML แม้ว่าพวกเขาจะซ่อนอยู่กับ CSS
Toni Leigh

คำตอบ:


545

ตอบสนองประมาณปี 2020

ในการonClickเรียกกลับให้เรียกฟังก์ชัน setter ของ state hookเพื่ออัพเดตสถานะและแสดงผลอีกครั้ง:

const Search = () => {
  const [showResults, setShowResults] = React.useState(false)
  const onClick = () => setShowResults(true)
  return (
    <div>
      <input type="submit" value="Search" onClick={onClick} />
      { showResults ? <Results /> : null }
    </div>
  )
}

const Results = () => (
  <div id="results" className="search-results">
    Some Results
  </div>
)

ReactDOM.render(<Search />, document.querySelector("#container"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>

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

JSFiddle

ตอบสนองประมาณปี 2014

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


3
ใช่ประเด็นที่ดีเกี่ยวกับสถานะอุปกรณ์ประกอบฉาก วิธีที่ดีกว่าในการทำเช่นนี้จะเหมือนในบทช่วยสอนที่นี่ที่แถบค้นหาและตารางผลลัพธ์เป็นพี่น้องแทนที่จะวางผลลัพธ์ไว้ในการค้นหา: facebook.github.io/react/docs/thinking-in-react.html
Douglas

53
ดังที่กล่าวไว้ในคำตอบอื่น ๆ การแทรก / การลบนั้นช้ากว่าการกำบังแบบง่าย ๆ
John Haugeland

4
ฉันคิดว่าความคิดเห็นของจอห์นต้องทบทวน ฉันไปพร้อมกับคำตอบที่ตั้งใจและนั่นก็เรียบร้อยและ 'รู้สึก' ตอบสนองมากขึ้นเช่น อย่างไรก็ตามฉันไม่สามารถตั้งค่าสถานะเริ่มต้นและสิ่งใดที่มีประโยชน์กับองค์ประกอบที่ไม่ได้ประกอบเข้าไป ฉันกำลังมองหาการใช้ CSS เพื่อซ่อนสิ่งต่าง ๆ แทน ผู้ฟังเกี่ยวกับองค์ประกอบที่ไม่ได้ต่อเชื่อมจะล้มเหลวอย่างเงียบ ๆ สิ่งนี้ทำให้ฉันสูญเสียครั้งใหญ่ในวันนี้
ลงจอด

นั่นหมายความว่าการตอบสนองจะแสดงผลคอมโพเนนต์เมื่อมีการเปลี่ยนแปลงสไตล์ (ถูกตั้งค่าให้แสดง / ซ่อน)!
alex

@ ดักลาสถ้าฉันไม่ได้ทำด้วยวิธีนี้จะไม่อนุญาตให้สลับกลับไปเป็นต้นฉบับ ฉันเดาว่า OP อาจไม่ต้องการ แต่ฉันจะรวมสิ่งนี้ได้อย่างไร
หนอน

221
<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>

12
จะเป็นการดีกว่าถ้าส่งคืน null แบบมีเงื่อนไขเช่นเดียวกับคำตอบของดักลาส ที่อนุญาตให้ React ลบออกจาก DOM ทั้งหมด ในกรณีของคุณ div & เนื้อหายังอยู่ใน DOM เพียงไม่แสดง สิ่งนี้อาจมีผลกระทบต่อประสิทธิภาพ
pmont

125
ความหมายด้านประสิทธิภาพนั้นแย่กว่ามากสำหรับการเพิ่มและลบองค์ประกอบ dom มากกว่าที่จะซ่อนและแสดงองค์ประกอบ ฉันตระหนักถึงความแตกต่างระหว่างวิธีการของเขาและของฉันและฉันเชื่อว่าคุณมีความผิดอย่างแน่นอน โปรดพิจารณาสละเวลาเพื่อกำหนด "ความหมายของประสิทธิภาพ" แล้ววัดค่า
John Haugeland

6
"Reflows รับประกันด้วยการเพิ่ม / ลบ" - ไม่ได้มีองค์ประกอบตำแหน่งที่แน่นอนซึ่งเป็นวิธีที่มีชื่อเสียงได้รับประสิทธิภาพที่น่าทึ่ง แต่คุณทำให้จุดที่ถูกต้องในการวัด
pmont

9
สำหรับสิ่งที่คุ้มค่าจะมีการกล่าวถึงในเอกสารตอบโต้ที่นี่: facebook.github.io/react/docs/…
Brad Parks

85
ดังนั้นฉันเพิ่งทดสอบการคืนค่า null เมื่อเทียบกับการตั้งค่าคลาสที่ซ่อนอยู่ด้วย 161 โหนด dom ที่ค่อนข้างใหญ่ มันเร็วกว่าการใช้คลาสอย่างมีนัยสำคัญมากกว่าการลบโหนด
Jonathan Rowny

120

นี่คือไวยากรณ์ทางเลือกสำหรับผู้ประกอบการที่ประกอบไปด้วย:

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

เทียบเท่ากับ:

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

ยันทำไม


ยังมีไวยากรณ์ทางเลือกด้วย display: 'none';

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

อย่างไรก็ตามหากคุณใช้มากเกินไปdisplay: 'none'สิ่งนี้จะนำไปสู่มลภาวะ DOM และทำให้ใบสมัครของคุณช้าลงในที่สุด


คำเตือน! ใช้วิธี 'double ampersand (&&)' สำหรับค่าบูลเท่านั้น {this.state.myComponents.length && <MyComponent />} จะแสดงผลเป็น 0 หาก myComponents ว่างเปล่าอาร์เรย์ (ตัวอย่าง)
Mega Proger

57

นี่คือแนวทางของฉัน

import React, { useState } from 'react';

function ToggleBox({ title, children }) {
  const [isOpened, setIsOpened] = useState(false);

  function toggle() {
    setIsOpened(wasOpened => !wasOpened);
  }

  return (
    <div className="box">
      <div className="boxTitle" onClick={toggle}>
        {title}
      </div>
      {isOpened && (
        <div className="boxContent">
          {children}
        </div>
      )}
    </div>
  );
}

ในรหัสด้านบนเพื่อให้บรรลุนี้ฉันใช้รหัสเช่น:

{opened && <SomeElement />}

ที่จะทำให้ SomeElementเฉพาะในกรณีที่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 (and false will be ignored by react during rendering)
// be careful with 'falsy' values eg
const someValue = 0;
someValue && <SomeElement /> // will output 0, which will be rednered by react
// it'll be better to:
!!someValue && <SomeElement /> // will render nothing as we cast the value to boolean

เหตุผลในการใช้วิธีนี้แทน CSS 'display: none';

  • ในขณะที่มันอาจ 'ถูกกว่า' ในการซ่อนองค์ประกอบด้วย CSS - ในกรณีเช่นนี้องค์ประกอบ 'ที่ซ่อนอยู่' ยังคงมีชีวิตอยู่ในโลกที่ตอบโต้ (ซึ่งอาจทำให้มันแพงกว่า)
    • หมายความว่าหากอุปกรณ์ประกอบฉากขององค์ประกอบหลัก (เช่น <TabView> ) จะเปลี่ยน - แม้ว่าคุณจะเห็นเพียงหนึ่งแท็บแท็บทั้ง 5 แท็บจะได้รับการแสดงผลอีกครั้ง
    • องค์ประกอบที่ซ่อนอยู่อาจยังคงมีวิธีการใช้งานรอบการทำงานบางอย่างเช่น มันอาจดึงข้อมูลบางอย่างจากเซิร์ฟเวอร์หลังจากอัพเดททุกครั้งแม้จะมองไม่เห็นก็ตาม
    • องค์ประกอบที่ซ่อนอยู่อาจทำให้แอปเสียหายหากได้รับข้อมูลที่ไม่ถูกต้อง อาจเกิดขึ้นเนื่องจากคุณสามารถ 'ลืม' เกี่ยวกับโหนดที่มองไม่เห็นเมื่อทำการอัพเดตสถานะ
    • คุณอาจตั้งค่ารูปแบบ 'แสดง' ผิดเมื่อทำการมองเห็นองค์ประกอบเช่น div บางอันคือ 'display: flex' โดยค่าเริ่มต้น แต่คุณจะตั้ง 'display: block' โดยไม่ได้ตั้งใจdisplay: invisible ? 'block' : 'none'ซึ่งอาจทำให้เลย์เอาต์เสียหาย
    • การใช้someBoolean && <SomeNode />นั้นง่ายมากที่จะเข้าใจและมีเหตุผลโดยเฉพาะอย่างยิ่งถ้าตรรกะของคุณเกี่ยวข้องกับการแสดงบางอย่างหรือไม่ซับซ้อน
    • ในหลายกรณีคุณต้องการสถานะองค์ประกอบ 'รีเซ็ต' เมื่อปรากฏขึ้นอีกครั้ง เช่น. คุณอาจมีแถบเลื่อนที่คุณต้องการตั้งค่าเป็นตำแหน่งเริ่มต้นทุกครั้งที่แสดง (ถ้าเป็นพฤติกรรมที่ต้องการรักษาสถานะองค์ประกอบก่อนหน้าแม้ว่ามันจะถูกซ่อนไว้ซึ่ง IMO หายาก - แน่นอนฉันจะใช้ CSS ถ้าจำสถานะนี้ในลักษณะที่แตกต่างกันจะซับซ้อน)

2
นี่เป็นตัวอย่างที่ยอดเยี่ยม! สิ่งเล็ก ๆ น้อย ๆ boxContent ควรเป็น className = "boxContent"
Bhetzie

5
มีข้อผิดพลาดอยู่ที่นี่: this.setState({isOpened: !isOpened});. อย่าพึ่งพาสถานะของตัวเองเมื่อคุณแก้ไขสถานะ นี่คือตัวอย่างที่ดี: reactjs.org/docs/...this.setState( s => ({isOpened: !s.isOpened}) )ดังนั้นมันควรจะเป็น: หมายเหตุฟังก์ชั่นลูกศรภายใน setState
arcol

คุณมีแหล่งที่มา / มาตรฐาน / ตัวอย่างยืนยันนี้ "ถ้าคุณตั้งค่าการแสดงผล: ไม่มี - องค์ประกอบยังคงแสดงผลโดยปฏิกิริยาและเพิ่มไปยัง DOM - ที่อาจมีผลกระทบต่อประสิทธิภาพการทำงานที่ไม่ดี" ?
neiya

@neiya ฉันทำไม่ได้ CSS อาจมีประสิทธิภาพมากกว่าโดยมีองค์ประกอบขนาดเล็ก แต่บ่อยครั้งที่คุณต้องการแสดงเนื้อหาส่วนใหญ่ที่เป็นทางเลือกเช่น แถบ ในขณะที่องค์ประกอบบางอย่างถูกซ่อนอยู่ด้วย CSS แต่ก็ยังมีชีวิตอยู่ในโลกที่ตอบสนอง หมายความว่ามันอาจอัพเดทเป็นสถานะดึงข้อมูลบางอย่าง ฯลฯ ซึ่งอาจมีราคาแพงและนำไปสู่พฤติกรรมที่ไม่คาดคิด และมันก็เป็น IMO ที่ง่ายมากที่จะนำไปใช้
pie6k


11

ฉันสร้างส่วนประกอบเล็ก ๆ ที่จัดการสิ่งนี้ให้คุณ: react-toggle-display

มันกำหนดคุณลักษณะของรูปแบบให้เป็นไปdisplay: none !importantตามhideหรือshowอุปกรณ์ประกอบฉาก

ตัวอย่างการใช้งาน:

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

มีคำตอบที่ยอดเยี่ยมหลายคำอยู่แล้ว แต่ฉันไม่คิดว่าพวกเขาได้รับการอธิบายที่ดีมากและวิธีการหลายอย่างที่ให้ไว้มี gotchas บางอย่างที่อาจทำให้คนเดินทาง ดังนั้นฉันจะไปสามวิธีหลัก (บวกหนึ่งตัวเลือกนอกหัวข้อ) เพื่อทำสิ่งนี้และอธิบายข้อดีข้อเสีย ฉันมักจะเขียนสิ่งนี้เพราะแนะนำให้ใช้ตัวเลือกที่ 1 มากและมีปัญหาที่อาจเกิดขึ้นกับตัวเลือกนั้นหากไม่ได้ใช้อย่างถูกต้อง

ตัวเลือก 1: การแสดงผลตามเงื่อนไขในพาเรนต์

ฉันไม่ชอบวิธีนี้เว้นแต่คุณจะแสดงองค์ประกอบเพียงครั้งเดียวแล้วปล่อยไว้ที่นั่น ปัญหาคือมันจะทำให้เกิดปฏิกิริยาตอบสนองในการสร้างองค์ประกอบตั้งแต่เริ่มต้นทุกครั้งที่คุณสลับการมองเห็น นี่คือตัวอย่าง 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, ฯลฯ โค้ดของคุณมีราคาแพงมันจะช้าลงอย่างมากในการแสดงส่วนประกอบ นอกจากนี้ยังหมายความว่าคุณไม่สามารถใช้สิ่งนี้กับส่วนประกอบที่เป็นสถานะที่คุณต้องการให้สถานะถูกเก็บรักษาไว้เมื่อถูกซ่อน (และเรียกคืนเมื่อแสดง) ข้อดีอย่างหนึ่งคือส่วนประกอบที่ซ่อนไม่ได้ถูกสร้างขึ้นจนกว่าจะถูกเลือก ดังนั้นส่วนประกอบที่ซ่อนไว้จะไม่ทำให้การโหลดหน้าเริ่มต้นของคุณล่าช้า อาจมีบางกรณีที่คุณต้องการให้องค์ประกอบที่เป็นสถานะที่จะรีเซ็ตเมื่อสลับ ในกรณีนี้นี่คือตัวเลือกที่ดีที่สุดของคุณ

ตัวเลือกที่ 2: การแสดงผลแบบมีเงื่อนไขในเด็ก

สิ่งนี้จะสร้างองค์ประกอบทั้งสองครั้ง จากนั้นทำให้วงจรการแสดงผลส่วนที่เหลือสั้นลงหากส่วนประกอบถูกซ่อน นอกจากนี้คุณยังสามารถลัดวงจรตรรกะอื่น ๆ ในวิธีอื่น ๆ โดยใช้เสาที่มองเห็นได้ สังเกตเห็น console.log ในหน้า codepen 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 นั้นใช้ได้และอาจเป็นตัวเลือกที่ดีที่สุด

หากการโหลดหน้าเว็บช้าเป็นปัญหาแสดงว่าคุณมีรหัสราคาแพงในวิธีการใช้รอบการทำงานและโดยทั่วไปก็ไม่ใช่ความคิดที่ดี คุณสามารถและควรแก้ปัญหาการโหลดหน้าเว็บช้าโดยการย้ายรหัสราคาแพงออกจากวิธีวงจรชีวิต ย้ายไปยังฟังก์ชัน async ที่ kicked off โดย ComponentDidMount และให้การเรียกกลับวางไว้ในตัวแปรสถานะด้วย setState () หากตัวแปรสถานะเป็นโมฆะและส่วนประกอบนั้นสามารถมองเห็นได้แล้วให้ฟังก์ชั่นการแสดงผลคืนตัวยึด มิฉะนั้นแสดงข้อมูล วิธีนี้หน้าจะโหลดอย่างรวดเร็วและเติมแท็บขณะที่โหลด นอกจากนี้คุณยังสามารถย้ายตรรกะไปที่ผู้ปกครองและผลักดันผลลัพธ์ไปยังเด็ก ๆ เป็นอุปกรณ์ประกอบฉาก วิธีนี้คุณสามารถจัดลำดับความสำคัญของแท็บที่โหลดก่อน หรือแคชผลลัพธ์และรันเฉพาะตรรกะในครั้งแรกที่ส่วนประกอบถูกแสดง

ตัวเลือก 3: การซ่อนคลาส

การซ่อนคลาสน่าจะเป็นวิธีที่ง่ายที่สุด ดังที่ได้กล่าวไว้คุณเพียงแค่สร้างคลาส CSS พร้อมจอแสดงผล: ไม่มีและกำหนดคลาสตามเสา ข้อเสียคือรหัสทั้งหมดของทุกองค์ประกอบที่ซ่อนอยู่เรียกว่าและส่วนประกอบที่ซ่อนอยู่ทั้งหมดจะแนบกับ DOM (ตัวเลือกที่ 1 ไม่ได้สร้างส่วนประกอบที่ซ่อนอยู่เลยและตัวเลือกที่ 2 ไม่จำเป็นต้องใช้รหัสลัดเมื่อส่วนประกอบถูกซ่อนและเอาส่วนประกอบออกจาก DOM ทั้งหมด) ดูเหมือนว่านี่จะเร็วกว่าในการสลับการมองเห็นตามการทดสอบบางอย่าง คำตอบอื่น ๆ แต่ฉันไม่สามารถพูดได้

ตัวเลือก 4: องค์ประกอบเดียว แต่เปลี่ยนอุปกรณ์ประกอบฉาก หรืออาจจะไม่มีส่วนประกอบเลยและแคช HTML

อันนี้จะไม่ทำงานสำหรับทุกแอปพลิเคชันและเป็นหัวข้อที่ปิดเพราะมันไม่ได้เกี่ยวกับการซ่อนส่วนประกอบ แต่มันอาจเป็นทางออกที่ดีกว่าสำหรับการใช้งานบางกรณีมากกว่าการซ่อน สมมติว่าคุณมีแท็บ อาจเป็นไปได้ที่จะเขียนหนึ่งองค์ประกอบการเกิดปฏิกิริยาและเพียงแค่ใช้อุปกรณ์ประกอบฉากเพื่อเปลี่ยนสิ่งที่ปรากฏในแท็บ คุณสามารถบันทึก JSX เพื่อระบุตัวแปรและใช้ prop เพื่อตัดสินใจว่า JSX ใดที่จะกลับมาในฟังก์ชั่นการแสดงผล หากต้องสร้าง JSX ให้ทำและแคชในพาเรนต์และส่งอันที่ถูกต้องเป็นเสา หรือสร้างในเด็กและแคชไว้ในสถานะของเด็กและใช้อุปกรณ์ประกอบฉากเพื่อเลือกหนึ่งที่ใช้งานอยู่


9

นี่เป็นวิธีที่ดีในการใช้งาน DOM เสมือน :

class Toggle extends React.Component {
  state = {
    show: true,
  }

  toggle = () => this.setState((currentState) => ({show: !currentState.show}));

  render() {
    return (
      <div>
        <button onClick={this.toggle}>
          toggle: {this.state.show ? 'show' : 'hide'}
        </button>    
        {this.state.show && <div>Hi there</div>}
      </div>
     );
  }
}

ตัวอย่างที่นี่

ใช้ React hooks:

const Toggle = () => {
  const [show, toggleShow] = React.useState(true);

  return (
    <div>
      <button
        onClick={() => toggleShow(!show)}
      >
        toggle: {show ? 'show' : 'hide'}
      </button>    
      {show && <div>Hi there</div>}
    </div>
  )
}

ตัวอย่างที่นี่


ฉันชอบคำตอบแบบลีนนี้ สงสารซอจะไม่ทำงาน
Juan Lanus

ตามที่ระบุไว้ในคำตอบก่อนหน้านี้คุณควรจะได้ขึ้นอยู่กับรัฐในการ this.setState()
Dan Dascalescu

8

คุณตั้งค่าบูลีนในสถานะ (เช่น 'แสดง)' แล้วทำดังนี้:

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

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

ฉันลองสิ่งนี้ แต่เหตุการณ์การคลิกไม่ได้เปลี่ยน css เพื่อแสดงบล็อก ฉันหลงทางในวิธีการทำให้สำเร็จ มีคำแนะนำเพิ่มเติมหรือไม่?
user1725382

1
สิ่งนี้เกี่ยวข้องกับการเปลี่ยนแปลงตารางกฎสไตล์ จะดีกว่ามากหากมีกฎเดียวที่คุณสามารถเปิดและปิดซึ่งไม่ได้เป็นส่วนหนึ่งของคุณสมบัติแบบไดนามิกของโหนด dom
John Haugeland

1
มันไม่สำคัญว่าคุณจะใช้คลาสหรือสไตล์ที่นี่ ... ดูเหมือนว่าคุณจะทำงานได้ดี
Brigand

2
การใช้คลาสจะเร็วขึ้นตามลำดับความสำคัญ เป็นเรื่องดีที่รู้
เจสันไรซ์

1
สามารถใช้ชื่อคลาสที่มีเงื่อนไขกับ: github.com/JedWatson/classnames
backdesk

7

แนวปฏิบัติที่ดีที่สุดอยู่ด้านล่างตามเอกสาร:

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

แสดงองค์ประกอบเฉพาะเมื่อสถานะนั้นถูกต้อง


คำตอบนี้ได้รับเมื่อปีที่แล้วดังนั้นมันก็โอเคที่จะลบมันตอนนี้
Dan Dascalescu

5
class Toggle extends React.Component {
  state = {
    show: true,
  }

  render() {
    const {show} = this.state;
    return (
      <div>
        <button onClick={()=> this.setState({show: !show })}>
          toggle: {show ? 'show' : 'hide'}
        </button>    
        {show && <div>Hi there</div>}
      </div>
     );
  }
}

4
   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

ฉันเริ่มต้นด้วยคำแถลงนี้จากทีม React:

ในการตอบสนองคุณสามารถสร้างองค์ประกอบที่แตกต่างที่ห่อหุ้มพฤติกรรมที่คุณต้องการ จากนั้นคุณสามารถแสดงผลได้เพียงบางส่วนขึ้นอยู่กับสถานะของแอปพลิเคชันของคุณ

การสร้างการแสดงผลแบบมีเงื่อนไขใน React ทำงานในลักษณะเดียวกับที่เงื่อนไขทำงานใน JavaScript ใช้โอเปอเรเตอร์ JavaScript เช่น if หรือโอเปอเรเตอร์ที่มีเงื่อนไขเพื่อสร้างองค์ประกอบที่เป็นตัวแทนของสถานะปัจจุบันและให้ React อัปเดต UI เพื่อให้ตรงกับพวกเขา

โดยทั่วไปคุณจะต้องแสดงองค์ประกอบเมื่อคลิกปุ่มคุณสามารถทำได้สองวิธีโดยใช้ Pure React หรือใช้ CSS โดยใช้วิธี React บริสุทธิ์คุณสามารถทำสิ่งต่าง ๆ เช่นโค้ดด้านล่างในกรณีของคุณดังนั้นในการเรียกใช้ครั้งแรกผลลัพธ์ จะไม่แสดงตามที่เป็นhideResultsอยู่trueแต่โดยการคลิกที่ปุ่มสถานะจะเปลี่ยนและhideResultsเป็นfalseและส่วนประกอบที่ได้รับการแสดงผลอีกครั้งด้วยเงื่อนไขค่าใหม่นี้เป็นเรื่องธรรมดาที่จะใช้การเปลี่ยนมุมมององค์ประกอบใน React ...

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

หากคุณต้องการที่จะทำการศึกษาต่อไปในการแสดงผลตามเงื่อนไขในการตอบสนองได้ดูที่นี่


1
นี่ควรจะเป็นวิธีที่สง่างามที่สุด!
ที่ห้า

4

ตัวอย่างการซ่อน / การแสดงที่เรียบง่ายด้วย React Hooks: (ไม่มีเรื่องซอ)

const Example = () => {

  const [show, setShow] = useState(false);

  return (
    <div>
      <p>Show state: {show}</p>
      {show ? (
        <p>You can see me!</p>
      ) : null}
      <button onClick={() => setShow(!show)}>
    </div>
  );

};

export default Example;

2
มันง่ายกว่าที่จะแค่แสดง { 1: 2}
Piotr Żak

3

หากคุณต้องการที่จะดูวิธีการสลับการแสดงของการชำระเงินซอนี้

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

วิธีง่ายๆในการแสดง / ซ่อนองค์ประกอบใน React using hooks

const [showText, setShowText] = useState(false);

ตอนนี้เรามาเพิ่มตรรกะในวิธีการเรนเดอร์ของเรา:

{showText && <div>This text will show!</div>}

และ

onClick={() => setShowText(!showText)}

ทำได้ดีมาก


2

ในบางกรณีองค์ประกอบการสั่งซื้อที่สูงขึ้นอาจเป็นประโยชน์:

สร้างส่วนประกอบคำสั่งซื้อที่สูงขึ้น:

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 ... /> }


1

ใช้โมดูลrc-if-else

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

ใช้การอ้างอิงและจัดการ CSS

วิธีหนึ่งอาจใช้ React's refและจัดการคลาส CSS โดยใช้ API ของเบราว์เซอร์ ประโยชน์ของมันคือหลีกเลี่ยงการแสดงซ้ำในการตอบสนองหากจุดประสงค์เดียวคือการซ่อน / แสดงองค์ประกอบ DOM บางอย่างในการคลิกปุ่ม

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

ป.ล. แก้ไขให้ฉันถ้าฉันผิด :)


ตัวอย่าง codesandbox.io สร้างที่นี่: utgzx.csb.appรหัสที่codesandbox.io/embed/react-show-hide-with-css-utgzx
ตบ

0

หากคุณใช้ bootstrap 4 คุณสามารถซ่อนองค์ประกอบด้วยวิธีนั้นได้

className={this.state.hideElement ? "invisible" : "visible"}

0

สิ่งนี้สามารถทำได้เช่นนี้ (วิธีที่ง่ายมาก)

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

โปรดอ่านเกี่ยวกับการตั้ง "รัฐบนพื้นฐานของรัฐก่อนหน้านี้" ที่reactjs.org/docs/react-component.html#setstate นอกจากนี้ยังเป็นการดีที่จะแก้ไขการเยื้องในตอนท้าย
Dan Dascalescu

0

ตัวอย่างนี้แสดงวิธีที่คุณสามารถสลับระหว่างส่วนประกอบต่าง ๆ โดยใช้สลับที่สลับหลังจากทุก 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);

URL ภาพแปลกคืออะไร คุณสามารถใช้บริการตัวยึดรูปภาพมาตรฐานเช่นplaceimg.com
Dan Dascalescu

0

ใช้รูปแบบลีนและไวยากรณ์แบบสั้น:

{ this.state.show && <MyCustomComponent /> }

บางทีคุณอาจขยายตัวในรูปแบบลีนและไวยากรณ์แบบสั้นเพื่ออธิบายวิธีการทำงาน โอ้รอที่ได้กระทำในคำตอบ3 ปีก่อนหน้านี้ คำตอบของคุณนำอะไรมาที่โต๊ะอีกครั้ง?
Dan Dascalescu

0

ที่นี่เป็นวิธีที่ง่ายมีประสิทธิภาพและดีที่สุดมาพร้อมกับ Classless React Component สำหรับการแสดง / ซ่อนองค์ประกอบ การใช้React-Hooksซึ่งมีอยู่ในโครงการcreate-react-app ล่าสุดที่ใช้React 16

import React, {useState} from 'react';
function RenderPara(){
const [showDetail,setShowDetail] = useState(false);

const handleToggle = () => setShowDetail(!showDetail);

return (
<React.Fragment>
    <h3>
        Hiding some stuffs 
    </h3>
    <button onClick={handleToggle}>Toggle View</button>
   {showDetail && <p>
        There are lot of other stuffs too
    </p>}
</React.Fragment>)

}  
export default RenderPara;

Happy Coding :)


0
//use ternary condition

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

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

{ this.state.yourState == 'string' ? <MyComponent /> : ''}

{ this.state.yourState == 'string' && <MyComponent /> }

//Normal condition

if(this.state.yourState){
 return <MyComponent />
}else{
  return null;
}

-1

คุณสามารถใช้ไฟล์ 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
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);

1
คุณสามารถอธิบายสิ่งที่คุณทำและทำไมมันถึงดีกว่าคำตอบที่ยอมรับ?
Seblor

-1
class App extends React.Component {
  state = {
    show: true
  };

  showhide = () => {
    this.setState({ show: !this.state.show });
  };

  render() {
    return (
      <div className="App">
        {this.state.show && 
          <img src={logo} className="App-logo" alt="logo" />
        }
        <a onClick={this.showhide}>Show Hide</a>
      </div>
    );
  }
}

คุณช่วยเพิ่มคำอธิบายเพื่อความเข้าใจที่ดีขึ้นได้ไหม ขอบคุณ!
Shanteshwar Inde

@ShanteshwarInde: นี่เป็นการทำซ้ำแนวคิดเดียวกันจากคำตอบก่อนหน้ารวมถึงการใช้ setState ที่ไม่ถูกต้องขึ้นอยู่กับสถานะปัจจุบัน ดูreactjs.org/docs/react-component.html#setstate : "หากคุณจำเป็นต้องตั้งค่าสถานะตามสถานะก่อนหน้าอ่านเกี่ยวกับอาร์กิวเมนต์ updater"
Dan Dascalescu

-1

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

var Results = React.createClass({
    render: function() {
        return (
            <div id="results" className="search-results">
                <input type="text" />
            </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>


4
ในขณะที่รหัสนี้อาจตอบคำถาม แต่มีบริบทเพิ่มเติมเกี่ยวกับสาเหตุและ / หรือวิธีการที่รหัสนี้ตอบคำถามช่วยปรับปรุงมูลค่าระยะยาว
xiawi

@xiawi พูดอะไร นอกจากนี้โปรดใช้constแทนvarเมื่อคุณประกาศค่าคงที่
Dan Dascalescu
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.