我有一个像这样的无状态组件:
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
组件,希望该组件将open
和open-active
类添加到我的项目中。
目前,一个项目的onClock都已打开,但我希望将它们分别处理。
我不确定如何使用状态和类来做到这一点。
感谢您的帮助
答案 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>
)
};
}