[javascript] React에서 요소 표시 또는 숨기기

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



답변

2020 년경 반응

에서 onClick콜백 통화 상태 후크의 상태를 업데이트 할 setter 함수를 다시 렌더링 :

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


답변

<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 오염으로 이어지고 결국 응용 프로그램 속도가 느려집니다.


답변

여기 내 접근 방식이 있습니다.

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: invisible ? 'block' : 'none'레이아웃을 깨뜨릴 수있는 실수로 ‘display : block’을 설정 합니다
    • 사용하는 someBoolean && <SomeNode />것은 이해하기 쉽고 매우 간단합니다. 특히 무언가를 표시하는 것과 관련된 논리가 복잡 해지는 경우
    • 대부분의 경우 요소 상태가 다시 나타날 때 ‘재설정’하려고합니다. 예. 표시 될 때마다 초기 위치로 설정하려는 슬라이더가있을 수 있습니다. (이전 요소 상태가 숨겨져 있어도 IMO가 거의 발생하지 않는 것이 바람직한 동작이라면-이 상태를 다른 방식으로 기억하는 것이 복잡 할 경우 실제로 CSS를 사용하는 것이 좋습니다)

답변

최신 버전의 0.11 반응으로 콘텐츠가 렌더링되지 않도록 null을 반환 할 수도 있습니다.

null로 렌더링


답변

나는 당신을 위해 이것을 처리하는 작은 구성 요소를 만들었습니다 : react-toggle-display

또는 props 를 display: none !important기반으로 스타일 속성을 설정합니다 .hideshow

사용법 예 :

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


답변

이미 몇 가지 훌륭한 답변이 있지만, 나는 그들이 잘 설명되지 않았다고 생각하며 주어진 방법 중 일부에는 사람들을 여행 할 수있는 문제가 있습니다. 이 작업을 수행하고 장단점을 설명하는 세 가지 주요 방법 (한 가지 주제 이외의 옵션)을 살펴 보겠습니다. 옵션 1을 많이 권장하고 올바르게 사용하지 않으면 해당 옵션에 많은 잠재적 인 문제가 있기 때문에 주로 이것을 쓰고 있습니다.

옵션 1 : 부모의 조건부 렌더링.

구성 요소를 한 번만 렌더링하고 그대로 두지 않는 한이 방법이 마음에 들지 않습니다. 가시성을 토글 할 때마다 구성 요소가 처음부터 새로 작성되도록하는 문제가 발생합니다. 다음은 그 예입니다. 부모 LoginControl에서 LogoutButton 또는 LoginButton이 조건부로 렌더링됩니다. 이것을 실행하면 각 버튼 클릭시 생성자가 호출되는 것을 알 수 있습니다. 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, 렌더링 등의 코드가 비싸면 구성 요소 표시 속도가 크게 느려집니다. 또한 숨겨져있을 때 상태를 유지하고 표시 할 때 복원하려는 상태 저장 구성 요소에는이 기능을 사용할 수 없습니다. 한 가지 장점은 숨겨진 구성 요소를 선택할 때까지 전혀 만들지 않는다는 것입니다. 따라서 숨겨진 구성 요소는 초기 페이지로드를 지연시키지 않습니다. 전환 할 때 상태 저장 구성 요소를 재설정하려는 경우도 있습니다. 어떤 경우에는 이것이 최선의 선택입니다.

옵션 2 : 자식의 조건부 렌더링

이렇게하면 두 구성 요소가 한 번 생성됩니다. 그런 다음 구성 요소가 숨겨져 있으면 나머지 렌더링 코드를 단락시킵니다. visible prop을 사용하여 다른 방법으로 다른 로직을 단락시킬 수도 있습니다. 코드 펜 페이지에서 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는 첫 페이지로드시 모든 구성 요소의 init를 실행합니다. 첫로드를 느리게합니다. 다시 참고해야합니다. 조건에 따라 구성 요소를 한 번만 표시하고 전환하지 않거나 toggledm 일 때 재설정하려는 경우 옵션 1이 적합하고 아마도 가장 좋은 옵션 일 것입니다.

그러나 느린 페이지로드가 문제인 경우 수명주기 방법에 값 비싼 코드가 있으며 일반적으로 좋은 생각이 아닙니다. 고가의 코드를 라이프 사이클 메소드에서 제거하여 페이지로드 속도가 느려질 수 있습니다. ComponentDidMount에 의해 시작된 비동기 함수로 이동하고 콜백이 setState ()를 사용하여 상태 변수에 넣도록합니다. 상태 변수가 null이고 구성 요소가 표시되면 render 함수가 자리 표시자를 반환하도록합니다. 그렇지 않으면 데이터를 렌더링하십시오. 이렇게하면 페이지가 빠르게로드되고 탭이로드 될 때 채워집니다. 논리를 부모로 이동하고 결과를 자식으로 소품으로 푸시 할 수도 있습니다. 이렇게하면 먼저로드 할 탭의 우선 순위를 지정할 수 있습니다. 또는 결과를 캐시하고 구성 요소가 처음 표시 될 때만 로직을 실행하십시오.

옵션 3 : 수업 숨기기

클래스 숨기기는 아마도 구현하기 가장 쉬운 방법 일 것입니다. 언급했듯이 display : none으로 CSS 클래스를 만들고 prop를 기반으로 클래스를 할당하십시오. 단점은 모든 숨겨진 구성 요소의 전체 코드가 호출되고 모든 숨겨진 구성 요소가 DOM에 첨부됩니다. (옵션 1은 숨겨진 컴포넌트를 전혀 생성하지 않습니다. 그리고 옵션 2는 컴포넌트가 숨겨진 경우 불필요한 코드를 단락시키고 컴포넌트를 DOM에서 완전히 제거합니다.) 다른 답변이지만 말할 수는 없습니다.

옵션 4 : 하나의 구성 요소이지만 소품을 변경하십시오. 또는 구성 요소가 전혀없고 HTML을 캐시 할 수도 있습니다.

이것은 모든 응용 프로그램에서 작동하지는 않으며 구성 요소를 숨기는 것이 아니기 때문에 주제와는 관련이 없지만 일부 사용 사례의 경우 숨기는 것보다 더 나은 솔루션 일 수 있습니다. 탭이 있다고 가정 해 봅시다. 하나의 React Component를 작성하고 props를 사용하여 탭에 표시되는 내용을 변경할 수 있습니다. JSX를 상태 변수에 저장하고 소품을 사용하여 렌더링 함수에서 반환 할 JSX를 결정할 수도 있습니다. JSX를 생성해야하는 경우이를 수행하고이를 상위에 캐시하고 올바른 것을 소품으로 보냅니다. 또는 자식에서 생성하여 자식 상태로 캐시하고 props를 사용하여 활성 상태를 선택하십시오.