繁体   English   中英

反应 - 在无状态组件中切换

[英]React - toggle in stateless component

我试图在像这样的无状态组件中切换div的可见性:

const playerInfo = (props) => {
  let isPanelOpen = false;
  return (
      <div onClick={() => isPanelOpen = !isPanelOpen }>Toggle</div>
      {isPanelOpen && <div className="info-panel">
        {this.props.children}
      </div>}
  );
};

我看到isPanelOpen的值更改为true ,但未显示该面板。 我假设这是因为这是无法再次调用的无状态函数,所以一旦我们返回jsx,它将具有false值,并且稍后不会更新它。 有没有办法解决这个问题,并避免通过另外4个父无状态组件来修改这个变量作为道具?

您不能通过直接为变量分配新值来告诉React重新呈现UI(在您的情况下,您执行了isPanelOpen = !isPanelOpen )。
正确的方法是使用setState

但是你无法在无状态组件中执行此操作,必须在有状态组件中执行此操作,因此您的代码应该如下所示

import React, {Component} from 'react';
class playerInfo extends Component {
    constructor(props){
        super(props);
        this.state = {
            isPanelOpen: false
        }
    }
    render() {
        return (
            <div onClick={() => this.setState({isPanelOpen: !this.state.isPanelOpen})}>Toggle</div>
            {this.state.isPanelOpen && <div className="info-panel">
              {this.props.children}
          </div>}
        );
    }
}

说明

记住两件事:
1)您的UI应仅绑定到this.state.XXXX (对于有状态组件)或props.XXX (对于无状态组件)。
2)更新UI的唯一方法是通过调用setState()方法,没有其他方法会触发React重新呈现UI。

但是......如何更新无状态组件,因为它没有setState方法?

一个答案 :无状态组件应该包含在另一个有状态组件中。

假设你的无状态组件叫做Kid ,你有另一个名为Mum有状态组件。

 import React, {Component} from 'react'; class Mum extends Component { constructor(props){ super(props); this.state = { isHappy: false } } render() { return ( <div> <button onClick={() => this.setState({isHappy: true})}>Eat</button> <Kid isHappy={this.state.isHappy}/> </div> ); } } const Kid = (props) => (props.isHappy ? <span>I'm happy</span> : <span>I'm sad</span>); 

我认为这是因为这是无法再次调用的无状态函数

基本上,重新渲染组件的唯一方法是更改​​状态或道具。 :)

因此,当您更改局部变量时,React不会收到有关它的通知,也不会开始协调

您可以使用本机Javascipt执行此操作,否则在React中您无法使用无状态组件执行此操作:)

const playerInfo = (props) => {
    let isPanelOpen = false;
    return ( <
        div onClick = {
            () => {
                if (document.getElementsByClassName("info-panel")[0].style.display == 'none') {
                    isPanelOpen = true;
                    document.getElementsByClassName("info-panel")[0].style.display = '';
                } else {
                    isPanelOpen = false;
                    document.getElementsByClassName("info-panel")[0].style.display = 'none';
                }
            }
        } > Toggle < /div> <
        div className = "info-panel" > {
            this.props.children
        } <
        /div>
    );
};

除非先前父级的状态发生更改并传递向下传播到功能组件的更新属性,否则功能组件不会重新呈现。 您可以从有状态父级传递onClick处理程序,并在触发onClick时从无状态组件中调用它。 父母将控制显示的切换并将其作为道具传递给孩子(参见下面的片段)。

要设计这个,您应该确定您的HOC(更高阶组件)是否应该负责UI状态。 如果是这样,那么它可以确定其子组件是否应该处于打开状态,然后将其作为属性传递给子状态。 如果这是一个应该独立于周围世界而打开和关闭的组件,那么它应该有自己的状态。 例如,如果您正在创建一个选项卡式窗口小部件,它应该可以控制自己的打开和关闭状态。

 class App extends React.Component { state= { isOpen: false } handleClick = () => { this.setState({ isOpen: !this.state.isOpen }) } render() { return ( <div> <YourComponent isOpen={this.state.isOpen} handleClick={this.handleClick} /> </div> ) } } const YourComponent = ({isOpen, handleClick} = props) => { const onClick = () => { if (handleClick) { handleClick(); } } return ( <div onClick={onClick}> {isOpen ? <h2>it is open</h2> : <h2>it is closed</h2> } </div> ) } ReactDOM.render(<App />, document.getElementById('root')); 
 <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="root"></div> 

如果您主要关心的是将属性/方法传递给太多组件,那么您可以创建一个纯组件 ,它可以让您访问状态,但不能访问React Component子类的所有开销。 您还可以考虑使用像Redux这样的状态管理工具。

您可以使用这样的useState挂钩来完成此操作:

import { useState } from "react";

            function playerInfo () {

        const [panel, setPanel] = useState(false);

        function toggleButton () {
            if(!panel) setPanel(true);
            else setPanel(false);
            }

        return (
            <div>
            <button onClick={toggleButton}>Toggle</div>
            panel ? {this.props.children} : null;
            </div>}
              );
            };

    export default playerInfo;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM