Реагировать - добавлять класс только при нажатии элемента - PullRequest
0 голосов
/ 04 декабря 2018

У меня есть один компонент без сохранения состояния, подобный этому:

    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;

onClick на один Panel компонент, который хочет этотдобавляет классы open и open-active к моему предмету.На данный момент onClock для одного элемента открываются, но я хочу, чтобы оба обрабатывались отдельно.

Я не уверен, как сделать это самым чистым способом, используя состояние и классы.

Спасибоза вашу помощь

Ответы [ 3 ]

0 голосов
/ 04 декабря 2018

Добавьте имя для каждого из ваших <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 выпередают имя элементу, из которого вы вызываете обработчик.

0 голосов
/ 04 декабря 2018

Интересно, что сегодня утром я просто написал нечто очень похожее на это.

Я сделал это примерно так (если вы хотите, чтобы одновременно открывалась только одна панель): вы можете увидеть, как это работает в песочнице здесь.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>
    )
  };
}
0 голосов
/ 04 декабря 2018

Для отслеживания этих панелей вам понадобится отдельное значение, как показано ниже.Я не тестировал код, но должен выглядеть следующим образом.

 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 .

...