我正在构建一个组件<ElementList>
,它接收道具中的元素数组,并构建一个<List>
,其中每个<ListItem>
都是数组的元素。
我将<ListItem>
一个名为<ElementShow>
的单独组件传递给了<Dialog>
,它包裹了一个材料-ui <ListItem>
组件。
单击<Dialog>
后,应该会打开特定<ElementShow>
组件的<ListItem>
。
目前,当我点击任意<Dialog>
时,无论我点击哪个<ListItem>
,它都会为数组的最后一个元素打开import React from 'react'
import {List, ListItem} from 'material-ui/List'
import Subheader from 'material-ui/Subheader'
import ElementShow from './ElementShow'
class ElementList extends React.Component {
constructor() {
super()
this.state = {
dialogOpen: false
}
}
handleOpen = () => {
this.setState({dialogOpen: true})
}
handleClose = () => {
this.setState({dialogOpen: false})
}
renderElements () {
const {elements} = this.props
if (elements.length < 1) {
return (
<ListItem
key='empty_element'
primaryText='No Elements Yet'
/>
)
} else {
return elements.map(element => {
return (
<ListItem
key={element._id}
primaryText={element.name}
onClick={this.handleOpen}
>
<ElementShow
dialogOpen={this.state.dialogOpen}
handleClose={this.handleClose} element={element} />
</ListItem>
)
})
}
}
render () {
return (
<List className='box'>
<Subheader>Elements</Subheader>
{this.renderElements()}
</List>
)
}
}
export default ElementList
。
以下是参考代码:
ElementList.js
import React from 'react'
import Dialog from 'material-ui/Dialog'
class ElementShow extends React.Component {
constructor (props) {
super(props)
this.state = {
open: props.dialogOpen
}
}
render () {
const { element, handleClose } = this.props
return (
<Dialog
title={element.name}
modal={false}
open={this.props.dialogOpen}
onRequestClose={handleClose}>
{element}
</Dialog>
)
}
}
export default ElementShow
ElementShow.js
{{1}}
我认为我需要将对话状态与特定字符相关联,但我还没有找到可行的方法。
感谢任何帮助/提示!
答案 0 :(得分:1)
嗯,你遇到的一个问题是this.state
是父组件的状态,并不是每个孩子特有的 - 所以当你写的时候
elements.map((element) => {
...
<ElementShow dialoagOpen={ this.state.dialogOpen } />
})
它会影响所有元素。
我会做的是像
class ElementList {
onClickElement = (element) => {
this.setState({
dialogOpen: true,
selectedElement: element
});
}
render() {
const mElements = elements.map((element) => {
/* I would suggest using a partial here, as opposed to what I've written */
return <ListItem onClick={ () => { this.onClickElement(element) } } />
});
const { selectedElement } = this.state;
return (
<div>
<List className='box'>
<Subheader>Elements</Subheader>
{ mElements }
</List>
{ selectedElement && (
<Dialog
title={ selectedElement.name }
modal={ false}
open={ this.state.dialogOpen }
element={ selectedElement }
onRequestClose={ this.handleClose }
>
{ selectedElement }
</Dialog>
) }
</div>
)
}
}
我认为这将实现你想要的。如果要隐藏对话框,请将this.state.dialogOpen
设置为false
并清除this.state.selectedElement
。
答案 1 :(得分:0)
您需要为每个呈现的对话框提供单独的状态(true或false)。
将每个元素的索引传递给handleOpen
和handleClose
函数,并使用它来切换正确的状态。
return elements.map((element, index) => {
return (
<ListItem
key={element._id}
primaryText={element.name}
onClick={() => this.handleOpen(index)}
>
<ElementShow
dialogOpen={this.state.dialogOpen[index]}
handleClose={this.handleClose(index)} element={element} />
</ListItem>
)
})
接下来,将状态设置为等于元素数量的数组,并将第一个对话框初始化为open。在打开/关闭函数中包含索引以访问数组的部分。
constructor(props) {
super(props)
this.state = {
dialogOpen: props.element.map((element, index) => {
return index === 0 ? true : false;
}
}
}
handleOpen = (index) => {
this.setState({ dialogOpen[index]: true })
}
handleClose = (index) => {
this.setState({ dialogOpen[index]: false })
}
答案 2 :(得分:0)
对于任何使用钩子的人来说,这是我的解决方案:
const [openDialog, setDialogOpen] = React.useState(false);
const [selectedElement, setSelectedElement] = React.useState();
const handleDialogOpen = (element) => {
setDialogOpen(true);
setSelectedElement(element);
};
return (
{elements.map((e) => (
...
<CardActionArea onClick={() => handleDialogOpen(e)}>
...
{selectedElement && (
<EditDialog
selectedElement={selectedElement}
openDialog={openDialog}
setOpenDialog={setDialogOpen}
/>
)}
))}
)