Javascript 在React中选择多个子元素之一的正确方法是什么?

Javascript 在React中选择多个子元素之一的正确方法是什么?,javascript,reactjs,Javascript,Reactjs,我的新React应用程序有一小部分,其中包含一块文本,AllLines,分为一行一行的组件,称为line。我想让它工作起来,这样当单击一行时,它将被选中并可编辑,而所有其他行将显示为元素。如何最好地管理此处的状态,以便在任何给定时间仅选择其中一行?我正在努力解决的部分是确定哪个行元素被单击,以便父元素可以更改其状态 我知道我可以用什么方法来做到这一点,但我对反应还比较陌生,我试图通过正确地做事来让自己的头脑进入“反应中思考”,因此我渴望找出在这种情况下的最佳做法 class AllLines e

我的新React应用程序有一小部分,其中包含一块文本,
AllLines
,分为一行一行的组件,称为
line
。我想让它工作起来,这样当单击一行时,它将被选中并可编辑,而所有其他行将显示为
元素。如何最好地管理此处的状态,以便在任何给定时间仅选择其中一行?我正在努力解决的部分是确定哪个
元素被单击,以便父元素可以更改其状态

我知道我可以用什么方法来做到这一点,但我对反应还比较陌生,我试图通过正确地做事来让自己的头脑进入“反应中思考”,因此我渴望找出在这种情况下的最佳做法

class AllLines extends Component {
    state = {
        selectedLine: 0,
        lines: []
    };

    handleClick = (e) => {
        console.log("click");
    };

    render() {
        return (
            <Container>
                {
                    this.state.lines.map((subtitle, index) => {
                        if (index === this.state.selectedLine) {
                            return (
                                <div id={"text-line-" + index}>
                                    <TranscriptionLine
                                        lineContent={subtitle.text}
                                        selected={true}
                                    />
                                </div>
                            )
                        }
                        return (
                            <div id={"text-line-" + index}>
                                <Line
                                    lineContent={subtitle.text}
                                    handleClick={this.handleClick}
                                />
                            </div>
                        )
                    })
                }
            </Container>
        );
    }
}
类所有行扩展组件{
状态={
所选行:0,
行:[]
};
handleClick=(e)=>{
控制台日志(“单击”);
};
render(){
返回(
{
this.state.lines.map((副标题,索引)=>{
if(index==this.state.selectedLine){
返回(
)
}
返回(
)
})
}
);
}
}
类行扩展组件{
render(){
if(this.props.selected==true){
返回(
)
}
返回(

{this.props.lineContent}

); } }
在您的情况下,没有更简单的方法。当前选定的
行的状态为“高于”行集合(父级),这是正确的(对于兄弟姐妹需要知道的情况)

但是,您可以大大简化代码:


{this.state.lines.map((副标题,索引)=>(
))}
对于
Line
组件,最好使用功能组件,因为它是无状态的,甚至不使用任何生命周期方法

编辑:添加了缺少的右括号

'Thinking in React',您可能希望放弃通过其唯一的
id
;)获取DOM元素的习惯

据我所见,您的代码库中缺少几个部分:

  • 一次只选择一行的智能单击处理程序
  • 编辑将坚持回调的行处理程序,该回调将修改父状态中的行内容
  • 对于能够编辑的行和实际编辑的行,最好有两个单独的组件,因为它们的行为方式不同,并且显示为不同的DOM元素
为了总结以上内容,我将稍微将您的代码改写为以下内容:

const{Component}=React,
{render}=ReactDOM
const linesData=Array.from(
{长度:10},
(u,i)=>`行号${i}出现了`
)      
类行扩展组件{
render(){
返回(

{this.props.lineContent}

) } } 类转录行扩展组件{ 建造师(道具){ 超级(道具) 此.state={ 内容:this.props.lineContent } this.onEdit=this.onEdit.bind(this) } onEdit(值){ this.setState({content:value}) this.props.pushEditUp(值,this.props.lineIndex) } render(){ 返回( this.onEdit(值)} /> ) } } 类AllLines扩展组件{ 建造师(道具){ 超级(道具) 此.state={ selectedLine:null, 台词:这个。道具。台词 } this.handleSelect=this.handleSelect.bind(this) this.handleEdit=this.handleEdit.bind(this) } handleSelect(idx){ this.setState({selectedLine:idx}) } handleEdit(newLineValue,lineIdx){ const linesShallowCopy=[…this.state.lines] LinesHallowCopy.splice(lineIdx,1,newLineValue) 这是我的国家({ 行:行HallowCopy }) } render(){ 返回( { this.state.lines.map((文本,索引)=>{ if(index==this.state.selectedLine){ 返回( ) } 其他的 返回( this.handleSelect(index)} /> ) }) } ) } } 渲染( , document.getElementById('root')) )

谢谢!我想我唯一的另一个问题是关于如何检索被单击元素的id。在div id上的那一刻,是否有任何方式(或原因)可以在子元素上实现这一点?谢谢你对简化的建议。我本来打算这么做,但现在还没来得及去做。你的
handleClick
可以返回一个当前
id
作为闭包的函数:
handleClick=(id)=>(event)=>this.setState({…selectedLine:id}尽管你已经得到了已接受的答案,但从你下面的评论看来,你的问题还没有完全解决。如果你的问题仍然存在,你不会介意考虑其他选项,你可能想退房,然后对输入的YvGEN进行实况演示,我已经把它变成了接受的答案SUNC。这更接近我想要的。我已经找到了解决方案
class Line extends Component {

    render() {
        if (this.props.selected === true) {
            return (
                <input type="text" value={this.props.lineContent} />
            )
        }
        return (
            <p id={} onClick={this.props.handleClick}>{this.props.lineContent}</p>
        );
    }
}
<Container>
{this.state.lines.map((subtitle, index) => (
    <div id={"text-line-" + index}>
        <Line
            handleClick={this.handleClick}
            lineContent={subtitle.text}
            selected={index === this.state.selectedLine}
        />
    </div>
))}
</Container>