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