React-仅在单击项目时添加类

时间:2018-12-04 17:08:39

标签: reactjs onclick classname

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

    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;

on点击一个Panel组件,希望该组件将openopen-active类添加到我的项目中。 目前,一个项目的onClock都已打开,但我希望将它们分别处理。

我不确定如何使用状态和类来做到这一点。

感谢您的帮助

3 个答案:

答案 0 :(得分:0)

您需要单独的值来跟踪这些面板,如下所示。我尚未测试代码,但应该看起来像这样。

 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软件包。

答案 1 :(得分:0)

为每个<Panel />组件添加一个名称:

<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组件中将名称传递给调用处理程序的元素。

答案 2 :(得分:0)

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

我这样做是这样的(如果您一次只想打开一个面板):您可以在此处的沙箱中看到它的工作。 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>
    )
  };
}