繁体   English   中英

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

[英]What is the correct way to select one of many child elements in React?

我有我的新 React 应用程序的一小部分,其中包含一个文本块AllLines ,拆分为名为Line的逐行组件。 我想让它工作,以便当单击一行时,它将被选中并可编辑,而所有其他行将显示为<p>元素。 我怎样才能最好地管理这里的状态,以便在任何给定时间只选择一行? 我正在努力解决的部分是确定以父元素可以更改其状态的方式单击了哪个Line元素。

我知道如何完成这项工作,但我对 React 比较陌生,并试图通过正确地做事来让我的头脑进入“在 React 中思考”,所以我很想知道在这种情况下什么是最佳实践.

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>
        );
    }
}
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>
        );
    }
}

在您的情况下,没有真正更简单的方法。 当前selected Line是“上方”行集合(父),这是正确的(对于兄弟姐妹需要知道的情况)。

但是,您可以简化代码很多

<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>

而对于Line组件,最好使用函数式组件,因为它是无状态的,甚至不使用任何生命周期方法。

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

“在 React 中思考”你会想要放弃通过它们的唯一id来获取 DOM 元素的习惯;)

据我所知,您的代码库中缺少一些部分:

  • 一次只选择一行的智能点击处理程序
  • 编辑行处理程序将坚持回调将修改父状态内的行内容
  • 最好是能够编辑的行和实际编辑的行的两个独立组件,因为它们的行为方式不同,并显示为不同的 DOM 元素

为了总结上述内容,我将您的代码稍微改写为以下内容:

 const { Component } = React, { render } = ReactDOM const linesData = Array.from( {length:10}, (_,i) => `There goes the line number ${i}` ) class Line extends Component { render(){ return ( <p onClick={this.props.onSelect}>{this.props.lineContent}</p> ) } } class TranscriptionLine extends Component { constructor(props){ super(props) this.state = { content: this.props.lineContent } this.onEdit = this.onEdit.bind(this) } onEdit(value){ this.setState({content:value}) this.props.pushEditUp(value, this.props.lineIndex) } render(){ return ( <input style={{width:200}} value={this.state.content} onChange={({target:{value}}) => this.onEdit(value)} /> ) } } class AllLines extends Component { constructor (props) { super(props) this.state = { selectedLine: null, lines: this.props.lines } 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] linesShallowCopy.splice(lineIdx,1,newLineValue) this.setState({ lines: linesShallowCopy }) } render() { return ( <div> { this.state.lines.map((text, index) => { if(index === this.state.selectedLine) { return ( <TranscriptionLine lineContent={text} lineIndex={index} pushEditUp={this.handleEdit} /> ) } else return ( <Line lineContent={text} lineIndex={index} onSelect={() => this.handleSelect(index)} /> ) }) } </div> ) } } render ( <AllLines lines={linesData} />, document.getElementById('root') )
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script><div id="root"></div>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM