Как сохранить значение состояния после повторного запуска setState

#reactjs #object #setstate

#reactjs #объект #setstate

Вопрос:

setLabels вызывается каждый раз, когда пользователь нажимает на флажок, в результате чего появляется список элементов, соответствующих выбранному идентификатору элемента. (НАПРИМЕР. если установлен флажок 1.3, цикл for выполняется через exportEntries, захватывает все значения объектов, соответствующие ключу 1.3)

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

Как бы я мог сохранить все ранее выбранные значения и добавить к состоянию вместо замены текущего набора состояний?

 setLabels = (e, itemId, itemLabel) => {

    let fillerArray = [];
    for (let item of this.state.exportEntries) {

      if (itemId in item) {
        fillerArray.push({ [itemLabel]: item[itemId] });
      }  

      this.setState({
        filteredArray: fillerArray
      });

    }

    console.log(this.state.filteredArray);

    e.preventDefault();
  }
  

При первом щелчке Вывод

 0: {First: "One"}
1: {First: "Two"}
2: {First: "Three"}
3: {First: "Four"}
4: {First: "Five"}
  

При втором нажатии кнопки Вывод

 0: {Second: "One"}
1: {Second: "Two"}
2: {Second: "Three"}
3: {Second: "Four"}
4: {Second: "Five"}
  

** РЕДАКТИРОВАТЬ для массивов объектов **

   const singleValue = [...this.state.selectedValues];

  for (let item of this.state.exportEntries) {
    if (id in item) {

      // This is pulling values from exportEntries that match the id 
      // of the 'label' selected. So 'First', 'Last', etc... all have 
      // an id that is passed to perform the check here.
      singleValue.push({ [label]: item[id] });
    }
  }

  for (var i = 0; i < singleValue.length; i  ) {
    merged.push({ ...this.state.selectedValues[i], ...singleValue[i]})
  }

  // This is where I'm trying to merge the two arrays
  // If I click First amp; Last this is returned: 

  // (10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
  //   0: {First: "First 1"}
  //   1: {First: "First 2"}
  //   2: {First: "First 3"}
  //   3: {First: "First 4"}
  //   4: {First: "First 5"}
  //   5: {Last: "Last 1"}
  //   6: {Last: "Last 2"}
  //   7: {Last: "Last 3"}
  //   8: {Last: "Last 4"}
  //   9: {Last: "Last 5"}

  // I want this:
  // (5) [{…}, {…}, {…}, {…}, {…}]
  //   0: {First: "First 1" , Last: "Last 1"}
  //   1: {First: "First 2", Last: "Last 2"}
  //   2: {First: "First 3", Last: "Last 3"}
  //   3: {First: "First 4", Last: "Last 4"}
  //   4: {First: "First 5", Last: "Last 5"}
  

Комментарии:

1. Вы уверены, что хотите запускать setState каждый раз в цикле, а не после завершения построения нового массива?

2. @Auskennfuchs я обязательно скорректирую структуру, чтобы включить этот комментарий. Тем не менее, мне все равно нужно как-то сохранить все предыдущие выборки. В любом случае, вы могли бы предоставить какую-нибудь документацию или пример того, как сохранить эти значения?

3. @SethSpivey не могли бы вы поделиться codesandbox MVP?

4. @DipenShah все это разбито на части, для которых требуются определенные ключи, и является частью гораздо более сложного проекта, создание которого в изолированной среде заняло бы слишком много времени. Я буду более чем счастлив объяснить или предоставить что-либо еще.

5. @SethSpivey уверен, что я добавил предложение, основанное на моем понимании.

Ответ №1:

Мне все еще сложно понять ваш вопрос, но, основываясь на моих лучших способностях, я пытаюсь предложить вам что-то, что может сработать.

Я создал POC, чтобы обойти эту проблему. Основная проблема заключается в том, что текущее состояние обновляется асинхронно, поэтому доступ к нему сразу после обновления не даст вам обновленного состояния.

В моем примере кода я добавил кучу флажков и onChange обновляю состояние, чтобы установить все выбранные флажки и выполнить обратный setSate вызов I am calling setLabels (который я до сих пор не понимаю, что он делает).

Здесь важно выполнить обработку после обновления состояния. Кроме того, глядя на ваш код, особенно выделяются две вещи:

  1. Вы вызываете this.setState({ filteredArray: fillerArray }); изнутри массива, который является избыточным, и вы просто хотите вызвать его один раз.
  2. Вы постоянно обновляете fillerArray с новым значением let fillerArray = []; , может быть, вы хотите let fillerArray = [...this.state.filteredArray]; сохранить старый выбор.

Взгляните на этот код POC:

 class SomeClass extends Component {
  state = {
    selectedItems: [],
    exportEntries: [],
    filteredArray: []
  };

  setLabels = (itemId, itemLabel) => {
    console.log(this.state.selectedItems);
  };

  handleCheckBoxChange = (isSelected, id, label) => {
    const newSelection = [...this.state.selectedItems];
    if (isSelected) {
      newSelection.push(label);
    } else {
      const index = newSelection.indexOf(label);
      newSelection.splice(index, 1);
    }

    this.setState({ selectedItems: newSelection }, () =>
      this.setLabels(id, label)
    );
  };

  render = () => (
    <div>
      <label>
        <input
          type="checkbox"
          onChange={(e) =>
            this.handleCheckBoxChange(e.target.checked, "name", "First")
          }
        />
        Item 1
      </label>
      <label>
        <input
          type="checkbox"
          onChange={(e) =>
            this.handleCheckBoxChange(e.target.checked, "name", "Second")
          }
        />
        Item 2
      </label>
      <label>
        <input
          type="checkbox"
          onChange={(e) =>
            this.handleCheckBoxChange(e.target.checked, "name", "Third")
          }
        />
        Item 3
      </label>
      <label>
        <input
          type="checkbox"
          onChange={(e) =>
            this.handleCheckBoxChange(e.target.checked, "name", "Fourth")
          }
        />
        Item 4
      </label>
      <div>
        {this.state.selectedItems.map((i) => (
          <p>{i}</p>
        ))}
      </div>
    </div>
  );
}
  

Комментарии:

1. @SethSpivey помогло ли это?

2. Это помогло! В настоящее время я работаю над добавлением нескольких элементов, которые более специфичны для проекта, и отмечу его, как только он будет завершен!

3. Очень быстро, не могли бы вы объяснить this.setState({ SelectedItems: newSelection }, () => this.setLabels(id, label) );

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

5. Взгляните на это: codesandbox.io/s/relaxed-cohen-cthx4 , я должен обновить логику для слияния.

Ответ №2:

Насколько я правильно понимаю ваше требование, вы хотите переключить флажки и сохранить список всех отмеченных элементов. У вас уже есть filteredArray . В setLabel методе вы должны добавить текущий элемент, если он был отмечен, или удалить его из списка, если он был снят. Событие должно предоставить вам эту информацию ( e.checked или что-то в этом роде).

 class SomeClass extends Component {
   state = {
     filteredArray: []
   }

   setLabels = (e, itemId, itemLabel) => {
     const { filteredArray } = this.state
     if(e.checked) {
       this.setState({
          filteredArray: [...filteredArray,{[itemLabel]: item[itemId]}]
       })
     } else {
        this.setState({
           filteredArray: filteredArray.filter(item => item[itemLabel]===undefined)
        })
     }
     console.log(this.state.filteredArray);
 
     e.preventDefault();
   }   
}
  

Если бы вы могли проверить элемент в событии, он не должен был быть добавлен в массив, поэтому он будет добавлен. В противном случае оно уже было добавлено и будет отфильтровано.
Фильтр выглядит немного странно. У вас есть itemId , который, я полагаю, уникален. Поэтому я бы предложил itemId явно добавить объект к объекту, чтобы иметь лучшие критерии фильтрации.
Код не тестируется, но он должен работать таким образом.

Также имейте в виду console.log , что will, вероятно, не дает вам правильного вывода, поскольку setState не является синхронным.

Комментарии:

1. Извините, после реализации этот элемент возвращается как неопределенный в else setState.