#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
(который я до сих пор не понимаю, что он делает).
Здесь важно выполнить обработку после обновления состояния. Кроме того, глядя на ваш код, особенно выделяются две вещи:
- Вы вызываете
this.setState({ filteredArray: fillerArray });
изнутри массива, который является избыточным, и вы просто хотите вызвать его один раз. - Вы постоянно обновляете 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.