【问题标题】:React - Add a class only when an item is clickedReact - 仅在单击项目时添加类
【发布时间】:2019-05-06 04:30:49
【问题描述】:

我有一个这样的无状态组件:

    import React from 'react';
    import PropTypes from 'prop-types';

    const Panel = (props) => {
      return(
        <div
          className={props.className}
          onClick={props.onClick}>
          <p>{props.firstChild}</p>
          <p>{props.secondChild}</p>
          <p>{props.thirdChild}</p>
        </div>
      )
    }

    Panel.propTypes = {
      onClick: PropTypes.func.isRequired,
      className:PropTypes.any.isRequired,
      firstChild: PropTypes.string.isRequired,
      secondChild: PropTypes.string.isRequired,
      thirdChild: PropTypes.string.isRequired,
    };

    export default Panel

我的 Class 组件是这样的:

    import React, { Component } from 'react';
    import Panel from './panel'

    class ImageGallery extends Component {
      constructor(props){
        super(props)
        this.state = {
          open: false,
        }
      }

      toggleOpen = () => {
        console.log('hi')
        this.setState({
          open: !this.state.open
        })
      }

      render() {
        return (
          <div className="panels">
            <Panel
              firstChild="Hey"
              secondChild="Let's"
              thirdChild="Talk"
              onClick={this.toggleOpen}
              className={this.state.open ? "panel panel1 open open-active " : "panel panel1"}
            />
            <Panel
              firstChild="Hey"
              secondChild="Give"
              thirdChild="Me"
              onClick={this.toggleOpen}
              className={this.state.open ? "panel panel2 open open-active " : "panel panel2"}
            />
          </div>
        )
      };
    }

    export default ImageGallery;

点击一个Panelcomponent 希望这个将openopen-active 类添加到我的项目中。 目前一个项目上的 onClock 都在打开,但我希望两者分开处理。

我不确定如何以最简洁的方式使用状态和类。

感谢您的帮助

【问题讨论】:

    标签: reactjs onclick classname


    【解决方案1】:

    您需要单独的值来跟踪这些面板,如下所示。我没有测试代码,但应该是这样的。

     import React, { Component } from 'react';
        import Panel from './panel'
    
        class ImageGallery extends Component {
          constructor(props){
            super(props)
            this.state = {
              panel1: {
                open: false
              },
              panel2: {
                open: false
              }
            }
          }
    
          toggleOpen = (key) => {
            console.log('hi')
            this.setState({
              [key]: {
                open: !this.state[key].open
              }
            })
          }
    
          render() {
            return (
              <div className="panels">
                <Panel
                  firstChild="Hey"
                  secondChild="Let's"
                  thirdChild="Talk"
                  onClick={() => this.toggleOpen('panel1')}
                  className={this.state.open ? "panel panel1 open open-active " : "panel panel1"}
                />
                <Panel
                  firstChild="Hey"
                  secondChild="Give"
                  thirdChild="Me"
                  onClick={() => this.toggleOpen('panel2')}
                  className={this.state.open ? "panel panel2 open open-active " : "panel panel2"}
                />
              </div>
            )
          };
        }
    
        export default ImageGallery;
    

    另外,为了方便管理className,建议使用classnames包。

    【讨论】:

    • 我尝试了您的解决方案,但不幸的是没有任何反应!我真的不明白为什么......
    • sin 你的代码不可运行,人们很难知道发生了什么,考虑使用codesandbox.io构建一个最小的例子
    • 你完全正确,我应该从一开始就这样做。在这里你可以找到代码的链接,你会看到行为。 codesandbox.io/s/3yw7r9o16q
    【解决方案2】:

    为您的每个&lt;Panel /&gt; 组件添加一个名称:

    <Panel
    name="Foo"
    isOpen={this.state.fooOpen}
    ...
    />
    <Panel
    name="Bar"
    isOpen={this.state.barOpen}
    ...
    />
    

    在您的处理程序中使用如下代码:

    toggleOpen = event => {
        if(event.target.name === "Foo") {
            this.setState({fooOpen: true})
        } else {
            this.setState({barOpen: true})
        }
    }
    

    确保在您的 Panel 组件中将名称向下传递给您从中调用处理程序的元素。

    【讨论】:

      【解决方案3】:

      有趣的是,我今天早上在我的应用程序中编写了与此非常相似的代码。

      我是这样做的(如果您只想一次打开一个面板):您可以在此处的沙箱中看到此操作。 https://codesandbox.io/s/mow9nyj958

      import React, { Component } from 'react';
      import Panel from './panel'
      
      class ImageGallery extends Component {
        constructor(props){
          super(props)
          this.state = {
            openPanel: undefined,
          }
        }
      
        toggleOpen = (panelNumber) => {
          console.log('hi')
          this.setState(prevState => ({
            openPanel: (prevState.openPanel === panelNumber) ? undefined : panelNumber 
          }))
        }
      
        render() {
          return (
            <div className="panels">
              <Panel
                firstChild="Hey"
                secondChild="Let's"
                thirdChild="Talk"
                onClick={() => this.toggleOpen(1)}
                className={`panel panel1 ${(this.state.openPanel === 1) ? "open open-active" : ""}`}
              />
              <Panel
                firstChild="Hey"
                secondChild="Give"
                thirdChild="Me"
                onClick={() => this.toggleOpen(2)}
                className={`panel panel1 ${(this.state.openPanel === 2) ? "open open-active" : ""}`}
              />
            </div>
          )
        };
      }
      
      export default ImageGallery;  
      

      但我假设您希望能够同时打开两个面板,因此您可以执行类似的操作。

      class ImageGallery extends Component {
        constructor(props){
          super(props)
          this.state = {
            panel1Open: false,
            panel2Open: false
          }
        }
      
        toggleOpen = (panelNumber) => {
          console.log('hi')
          this.setState(prevState => {
            const key = `panel${panelNumber}Open`;
            return { [key]: !prevState[key] }
          })
        } 
        render() {
          return (
            <div className="panels">
              <Panel
                firstChild="Hey"
                secondChild="Let's"
                thirdChild="Talk"
                onClick={() => this.toggleOpen(1)}
                className={`panel panel1 ${this.state.panel1Open ? "open open-active" : ""}`}
              />
              <Panel
                firstChild="Hey"
                secondChild="Give"
                thirdChild="Me"
                onClick={() => this.toggleOpen(2)}
                className={`panel panel1 ${this.state.panel2Open ? "open open-active" : ""}`}
              />
            </div>
          )
        };
      }
      

      【讨论】:

      • 感谢您的回复,有趣的是您有同样的挑战!不幸的是,我试图实施您的解决方案,但没有任何反应。我只需要同时打开一个面板,所以我宁愿选择你的第一个提议。仍在寻找如何解决这个问题...
      • 在这里我创建了一个代码框,以便您可以更好地查看它codesandbox.io/s/3yw7r9o16q
      • 嗨@Fabian,这是一个沙盒,第一个命题有效。 codesandbox.io/s/mow9nyj958 对不起,在我上面的回答中,我犯了一个错误,破坏了代码。我已经在上面修复了,你可以在sandox中正常看到它
      • 非常感谢这次它按预期工作!感谢您抽出宝贵的时间,非常感谢:)
      猜你喜欢
      • 1970-01-01
      • 2018-03-28
      • 1970-01-01
      • 1970-01-01
      • 2021-11-27
      • 2022-12-17
      • 1970-01-01
      • 1970-01-01
      • 2013-01-24
      相关资源
      最近更新 更多