Только нажатие одного элемента в массив

У меня есть компонент, который вы можете включить/выключить, нажав на него:

clickHandler = () => {
    this.setState({active: !this.state.active})
    this.props.getSelection(this.state.active)
}

render() {
    const { key, children } = this.props;
    return (
        <button
            key = {key}
            style = {{...style.box, background: this.state.active ? 'green' : ''}}
            onClick = {() => this.clickHandler()}
        >
            {children}
        </button>
    );
}

В родительском компоненте я передаю метод для пытаться и получаю значение выбранного элемента, помещенного в массив, например так:

getSelection = (val) => {
    const arr = []
    arr.push(val);
    console.info(arr, 'arr');
}

Моя проблема в том, что он добавляет только один элемент в массив, поэтому длина массива всегда равна 1 (даже если было нажато более одного элемента).

Текущий результат (после того, как вы нажали все три)

console.info(arr, 'arr') // ["Birthday"] "arr"

Ожидаемый результат (после того, как вы нажали все три)

console.info(arr, 'arr') // ["Birthday", "Christmas", "School achievement"] "arr"

Ссылка на Кодепен

Есть идеи?

каждый раз, когда вызывается { const arr = [] arr.push(val); console.info(arr, 'arr') }, он создает пустой массив, в который вы помещаете один элемент, так что, конечно, это всегда 1 длина — вам нужно объявить arrза пределами этой функции

Jaromanda X 28.03.2019 02:03

Попробуйте определить константу arr вне функции getSelection.

Brian Peacock 28.03.2019 02:04
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
2
1 221
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Две вещи: setState является асинхронным, поэтому в следующей строке вы можете получить или не получить последнее значение, поэтому я рекомендую изменить

clickHandler = () => {
    this.setState({active: !this.state.active})
    this.props.getSelection(this.state.active)
  }

к

clickHandler = () => {
   this.setState({active: !this.state.active}, () => {
      this.props.getSelection(this.state.active)
   })
}

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

Во-вторых, в getSelection вы определяете новый массив каждый раз, когда попадаете туда, поэтому он не будет иметь значений из предыдущего запуска. Вы должны хранить его где-то.

Нет проблем, я рад, что это помогло. Если вы хотите отслеживать выбранные элементы, вам может понадобиться что-то вроде этого: Кодепен

nico.amabile 28.03.2019 02:41

Здесь есть 2 проблемы:

  1. arr — локальная переменная. Он не сохраняет предыдущий результат onClick.

  2. setState — это асинхронное событие. Согласно документация:

    setState() does not always immediately update the component.

    setState((state, props) => {}, () => { /*callback */}) следует использовать.

class Box extends React.Component {
  state = {
    active: false
  };

  clickHandler = () => {
    this.setState(
      state => ({ active: !state.active }),
      () => {
        this.props.getSelection(this.state.active);
      }
    );
  };

  render() {
    const { children } = this.props;
    return (
      <button
        style = {{ ...style.box, background: this.state.active ? "green" : "" }}
        onClick = {this.clickHandler}
      >
        {children}
      </button>
    );
  }
}

Незначительное примечание:

Значение key отсутствует в дочернем компоненте this.props, поэтому вам не нужно его передавать, но это не повлияет на результат.

В компоненте App давайте создадим массив на уровне класса для отображения:

class App extends React.Component {
  state = {
    needsOptions: ["Birthday", "Christmas", "School achievement"]
  };

  arr = [];

  getSelection = val => {
    this.arr.push(val);
    console.info(this.arr);
  };
}

CodePen здесь

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