#javascript #reactjs #asynchronous #setstate
#javascript #reactjs #асинхронный #setstate
Вопрос:
У меня есть эта createRoleMember
функция, которая обновляет состояние компонента, поэтому React может повторно отображать table () внутри компонента и отображать недавно добавленные roleMembers
строки.
createRoleMember = (newRoleMember) => {
this.setState((prevState) => {
return { roleMembers: prevState.roleMembers.concat([newRoleMember]) };
});
};
Код работает, когда я добавляю один элемент, но если массив содержит более одного значения, createRoleMember
функция повторно отображает таблицу с правильным количеством новых строк, но с тем же повторяющимся именем пользователя (всегда дублируя последнее имя пользователя в массиве).
Например, если массив выглядит следующим образом `[«testOne, «TestTwo», «testThree»], таблица будет повторно отображена следующим образом:
testthree xxx Aug 25, 2020
testthree xxx Aug 25, 2020
testthree xxx Aug 25, 2020
Вместо:
testtone xxx Aug 25, 2020
testttwo xxx Aug 25, 2020
testthree xxx Aug 25, 2020
Если я перезагружаю страницу, в таблице отображаются правильные данные.
Как я могу вызвать createRoleMember
(который содержит setState
) внутри цикла?
Больше контекста
createRoleMember
Функция вызывается в цикле, который выглядит следующим образом:
aliasArray.forEach((currAlias) => {
memberAttributes.alias = currAlias;
const marshalledObj = AWS.DynamoDB.Converter.marshall(memberAttributes);
const params = {
TableName: "xxxx",
Item: marshalledObj,
};
axios
.post(
"https://xxxxxx.execute-api.us-west-2.amazonaws.com/xxx/xxx",
params
)
.then(() => {
createRoleMember(memberAttributes);
const newRow = document.getElementById(
`${memberAttributes.alias}-${memberAttributes.Role}`
);
newRow.classList.add("new-row");
});
});
-
aliasArray
: массив строк типа «username1», «username2». -
memberAttributes
: объект с данными участника, например, username, grantedBy, grantedOn. -
newRow
: позволяет мне предоставлять обратную связь пользователю (выделяет новую строку зеленым цветом).
Ответ №1:
Я полагаю, что проблема в вашем коде здесь:
aliasArray.forEach((currAlias) => {
memberAttributes.alias = currAlias; // Here's the problem
// ...
axios
.post(/*...*/)
.then(() => {
createRoleMember(memberAttributes);
// ...
});
});
Каждый раз, когда вызывается обратный вызов forEach , вы обновляете значение memberAttributes.alias
. Итак, после того, как все члены aliasArray
были повторены, значение memberAttributes.alias
является последним значением aliasArray
.
Итак, когда ваши запросы возвращаются и выполняется успешный обратный вызов ( .then(...)
), memberAttributes.alias
это будет последнее значение aliasArray
для каждого вызова. Я полагаю, что ваша проблема будет решена путем распространения currAlias
до успешного обратного вызова, например:
aliasArray.forEach((currAlias) => {
memberAttributes.alias = currAlias;
const marshalledObj = AWS.DynamoDB.Converter.marshall(memberAttributes);
const params = {
TableName: "xxxx",
Item: marshalledObj,
};
axios
.post(
"https://xxxxxx.execute-api.us-west-2.amazonaws.com/xxx/xxx",
params
)
.then(() => {
memberAttributes.alias = currAlias;
createRoleMember(memberAttributes);
const newRow = document.getElementById(
`${currAlias}-${memberAttributes.Role}` // Modified this line
);
newRow.classList.add("new-row");
});
});
createRoleMember = (newRoleMember) => {
this.setState((prevState) => {
return { roleMembers: prevState.roleMembers.concat([{...newRoleMember}]) };
});
};
Комментарии:
1. Почему я не могу сделать
memberAttributes.alias = currAlias
сразу послеthen
? Я пытался и не сработало, и поскольку это не работает, почемуcreateRoleMember(memberAttributes,currAlias)
должно работать? Странная причина, если яconsole.log(currAlias)
получу два журнала с ожидаемыми значениями. Спасибо за вашу помощь, я ценю это!2. @TheDaniel Хороший момент, вы должны иметь возможность обновлять
memberAttributes.alias
в then и избавлять себя от изменения подписиcreateRoleMember
. Я полагаю, что здесь есть небольшая ошибка. Вы обновляете,memberAttributes
а затем (вcreateRoleMember
) вы переносили это в состояние. Но вы никогда не переназначаетеmemberAttributes
, поэтому каждый объект в состоянии фактически является ссылкой на один и тот же объект . Я обновил свой ответ, чтобы включить исправление этой проблемы. Обратите внимание, что теперь я использую оператор распространения объекта в createRoleMember для создания нового объекта.