Реакция - Ввод теряет фокус, когда setState вызывается для совершенно другого компонента. - PullRequest
0 голосов
/ 12 октября 2019

Я новичок в React и все еще в процессе обучения, терпите меня. У меня проблема с приложением React, поскольку мой ввод теряет фокус после ввода одной буквы. Я разбил текстовое поле на компонент самостоятельно. Однако, кажется, когда я вызываю setState для элемента в другом компоненте, это вызывает эту проблему.

У меня есть три компонента DropdownTextComponent, DisplayedColumnsList и AvailableColumnsList в одном большом компоненте DropdownComponent.

Это мой DropdownComponent, который содержит три различных компонента.

const DropdownComponent = (props) => {
    return (
        <div className = "dropdown-column">
            <Dropdown
                isOpen = {this.state.dropdownOpen}
                onClose = {() => this.setOpen(false)}
            >
                {props.dropdownsearch}
                {props.displayedcolumns}
                {props.availablecolumns}
            </Dropdown>
        </div>
    );
}

Это мой DropdownTextComponent:

const DropdownTextComponent = () => {
    return (
        <div className = "dropdown-text-input">
            <TextInput
                onChange = {this.dropdownSearch}
                value = {this.state.dropdownValue}
            >
            </TextInput>
        </div>
    )
}

Этометод dropdownSearch, который называется onChange:

dropdownSearch(e) {
    this.state.dropdownValue = e.target.value;
    let resultCols = this.state.columns;
    let dropdownSearchList = []

    let dropdownSet = new Set();
    for (let i = 0; i < resultCols.length; i++) {
        if (resultCols[i].text.includes(e.target.value)) {
            dropdownSet.add(resultCols[i]);
        }
    }
    dropdownSearchList = [...dropdownSet]
    this.setState({
        toggleColumnList : dropdownSearchList
    })
}

Теперь toggleColumnList используется в двух различных компонентах DisplayedColumnsList и AvailableColumnsList, поэтому я предполагаю, что при использовании setState здесь, он не должен повторно отображать DropdownTextComponent. Но он делает это, и мое поле ввода теряет фокус. Я прокомментировал часть setState, и она отлично работает.

Я хотел бы знать, в чем проблема и как ее решить. Пожалуйста, дайте мне знать, если вам нужна дополнительная информация по этому вопросу.

1 Ответ

0 голосов
/ 12 октября 2019

Что-то вроде этого может работать лучше?

class App extends React.Component {
    constructor (props) {
        super(props)
        this.state = {
            toggleColumnList: []
            dropdownValue: '',
            columns: [  { text: 'some text'}, { text: 'some other text'} ]
        }
    }

    dropdownSearch = (e) => {
        const value = e.target.value;
        let resultCols = this.state.columns;
        let dropdownSearchList = []

        let dropdownSet = new Set();
        for (let i = 0; i < resultCols.length; i++) {
            if (resultCols[i].text.includes(e.target.value)) {
                dropdownSet.add(resultCols[i]);
            }
        }
        dropdownSearchList = [...dropdownSet]
        this.setState({
            dropdownValue: value,
            toggleColumnList : dropdownSearchList
        })
    }

    render () {
        const { columns, toggleColumnList, dropdownValue } = this.state
        return (
            <DropdownComponent>
                <DropdownTextComponent value={dropdownValue} onChange={this.dropdownSearch}/>
                <DisplayedColumnsList columns={toggleColumnList.length ? toggleColumnList : columns} />
                <AvailableColumnsList columns={toggleColumnList.length ? toggleColumnList : columns} />
            </DropdownComponent>
        )
    }
}

class DropdownComponent extends React.Component {
    constructor (props) {
        super(props)
        this.state = {
            isOpen: true
        }
    }
    close = () => {
        this.setState({
            isOpen: false
        })
    }
    render () {
        return (
            <div className = "dropdown-column">
                <Dropdown
                    isOpen={this.state.isOpen}
                    onClose={this.close}
                >
                { props.children }
                </Dropdown>
            </div>
        )
    }
} 

const DropdownTextComponent = (props) => {
    const { onChange, value } = props
    return (
        <div className = "dropdown-text-input">
            <TextInput
                onChange={onChange}
                value={value}
            />
        </div>
    )
}

Обновление
В основном я пытался представить, как может выглядеть структура вашего компонента.

Суть в том, что вы хотите, чтобы ваш DropdownTextComponent отображал только при изменении его значения или обработчика события изменения.
Чтобы это произошло, вам следует избегать его явного отображения каждый раз, когда вы выполняете DropdownComponent, как вы это делали, но разрешите Reactсправиться с повторной сдачей для вас.

Когда вы делаете что-то подобное props={ <DropdownTextComponent /> }, выражение в скобках вычисляется сразу, при каждом рендеринге компонента. Более того, вы ничего не передаете дочернему компоненту.
Но если вы сделаете что-то подобное <DropdownComponent><DropdownTextComponent value={value} onChange={onChange} /></DropdownComponent> React проанализирует всю структуру вашего приложения и отобразит каждый узел, только если его реквизиты или состояние изменились.

Чтобы это работало, поскольку родительский элемент здесь является настраиваемым компонентом, вам придется явно добавить его дочерние элементы в метод визуализации. Вы можете сделать это, используя специальный React prop children, который содержит все, что вы определили как потомок вашего компонента.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...