React chained setState прерывание рендеринга

Я пытаюсь создать компонент RadioInput в ответ, однако, когда я добавляю обратный вызов, чтобы установить состояние внутри родительского элемента, кнопки не остаются нажатыми.

Внутри функции рендеринга компонентов RadioInput я создаю такие внутренние кнопки:

this.props.buttons.map( (button) => {
    return (
        <div ...>
            <Button clickedDown = {this.state.selectedButton === button} clickAction = {() => this.radioSelected(button)}.../>
        </div>
    )
}

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

radioSelected = (button) => {
    if (this.state.selectedButton !== button) {
        this.setState({selectedButton: button}, () => {
            this.props.clickAction(this.state.selectedButton);
        }
    }
}

RadioInput объявлен внутри родительского элемента следующим образом:

render () {
    const buttonList = [
        { color:'green', text:'Green', id: 1 },
        { color:'blue', text:'Blue', id: 2 },
        { color:'purple', text:'Purple', id: 3 }
    ];
    return (
        <RadioInput buttons = {buttonList} clickAction = {this.radioAction}/>
    )
}

Функция radioAction, вызываемая внутренней функцией RadioInput RadioSelected, выглядит следующим образом:

radioAction = (button) => {
    this.setState({
        team: button.color
    });
}

Если я удалю this.props.clickAction(this.state.selectedButton); из setState внутри радиовхода, он будет работать нормально. Если я удалю setState внутри родительского radioAction(), если он работает правильно. Почему связанные цепочкой setStates вызывают ошибки, такие как остановка clickedDown = {this.state.selectedButton === button}, чтобы не переоценивать?

Любая помощь приветствуется!

возможно, если бы вы могли проиллюстрировать, что вы пытаетесь сделать, я могу вам помочь, но мне не ясно, чего вы пытаетесь достичь

Lelouch 07.05.2018 22:57

В radioInput, когда вы нажимаете кнопку, она переводит кнопку в состояние clickedDown. Когда пользователь нажимает, я хочу отправить значение кнопки родительскому элементу (общей форме), чтобы он мог использовать эти данные при отправке формы. Когда я использую его, состояние обоих устанавливается правильно, но кнопка не переходит в состояние clickedDown.

Jared Jones 07.05.2018 23:04

Если ваше состояние установлено правильно, то пробовали ли вы, действительно ли эта опора clickedDown работает? Например, можно установить статическое значение true и посмотреть, что вы получите?

Lelouch 07.05.2018 23:23
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
3
448
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ваш clickAction не получает параметры:

clickAction = {() => this.radioSelected(button)}

Он сломался, потому что вы вызвали его с параметром, в то время как clickAction prop не получает ваш параметр, поэтому он просто не получает this.state.selectedButton

this.props.clickAction(this.state.selectedButton);

Итак, должно быть:

clickAction = {(button) => this.radioSelected(button)}

На самом деле это вызывает больше проблем, если я дам параметр, он связывает его как прокси. Я использую закрытие, чтобы привязать область видимости, чтобы у нее был доступ к кнопке. Когда я распечатываю button в radioSelected(), поскольку код в настоящее время правильно получает значение кнопки { color:'green', text:'Green', id: 1 }. Как я уже сказал, код работает отлично, пока я не добавлю строку this.props.clickAction(this.state.selectedButton); внутри обратного вызова RadioInputs setState.

Jared Jones 07.05.2018 22:29

Замечу, что если я уберу setState в родительской функции radioAction, то код тоже будет работать корректно. Ищу, почему последовательный setStates вызывает ошибки

Jared Jones 07.05.2018 22:36
Ответ принят как подходящий

Tl; доктор

x0 = [{a: 'red'}];
x1 = [{a: 'red'}];
console.info(x0[0] === x1[0]); // false 

Переместите инициализацию buttonList (const buttonList = ...) из функции render в конструктор или любое другое место, которое не изменяет массив при каждом рендеринге.

Объяснение

В вашем родителе вы повторно инициализируете buttonList каждый раз, когда вызывается render. Итак, после каждого вызова родительского render у вас будет другой buttonList, потому что каждый раз это новый объект.

Теперь ваша функция radioAction вызывает setState для родительского объекта, который вызывает render и эффективно заменяет все элементы buttonList на новый массив элементов. И определенно this.state.selectedButton не равен ни одному из них, так как это элемент из прежнего массива.

Другие вопросы по теме