Why does React only save the last element in my array? I have two elements, map over them and only the last element is put in the hook each time.
React.useEffect(() => {
if (bearbeiten) {
handleClickUserList(bearbeiten.user);
setBeschreibung(bearbeiten.beschreibung);
setKontaktNamenData([]);
{
bearbeiten.freunde?.map((freund) => {
setKontaktNamenData([...kontaktNamenData, freund.id]);
});
}
}
}, [bearbeiten]);
The passed array contains two objects of type Friends:
When saving, however, only the last element from the hook array is displayed or accepted:
CodePudding user response:
The current value of your variable doesn't get updated during the same iteration of the loop, so your setKontaktNamenData
calls are using a single value of kontaktNamenData
that triggered this effect. You are then setting the state variable to a new value each time, so the second setKontaktNamenData
is overwriting the first. It would be better to map your values first, and then set the state variable with the whole mapped array. You also don't need to set it to an empty array first, and this in fact will confuse other parts of your component that depend on kontaktNamenData
. The current state of your effect would require kontaktNamenData
to be a dependency, but you don't want to have a dependency of a value that gets set from within the effect, since it will trigger an infinite loop.
React.useEffect(() => {
if (bearbeiten) {
handleClickUserList(bearbeiten.user);
setBeschreibung(bearbeiten.beschreibung);
var ids = bearbeiten.freunde?.map((freund) => freund.id);
setKontaktNamenData(ids);
}
}, [bearbeiten]);
If you ever do actually need the old value of a state variable, use the callback when setting the new value instead of explicitly calling the name:
setKontaktNamenData(previousValue => previousValue.concat(newValue))
CodePudding user response:
You are enqueueing state updates in a loop but neglecting to use a functional state update. This means that the same current kontaktNamenData
from the enclosure is used each time. Each enqueued state update overwrites the previous update, so the last update processed is the one that is the value for the next render cycle.
A functional state update will correctly update from the previous state instead of the stale value from the enclosure.
Example:
React.useEffect(() => {
if (bearbeiten) {
handleClickUserList(bearbeiten.user);
setBeschreibung(bearbeiten.beschreibung);
setKontaktNamenData([]);
bearbeiten.freunde?.map((freund) => {
setKontaktNamenData(kontaktNamenData => [
...kontaktNamenData,
freund.id
]);
});
}
}, [bearbeiten]);
Alternatively you can enqueue a single state update and move the friends mapping into the functional state update.
Example:
React.useEffect(() => {
if (bearbeiten) {
handleClickUserList(bearbeiten.user);
setBeschreibung(bearbeiten.beschreibung);
setKontaktNamenData((bearbeiten.freunde || []).map((freund) => freund.id));
}
}, [bearbeiten]);
CodePudding user response:
Is this what you are asking for ?
React.useEffect(() => {
if (bearbeiten) {
handleClickUserList(bearbeiten.user);
setKontaktNamenData(o => [...o, ..._.pluck(bearbeiten.freunde, 'id')]);
}
}, [bearbeiten]);
I have removed few lines because according to me they were not making sense. example
// Setting this doesnt make sense because just after it you have written following.
setKontaktNamenData([]);
...
-> setKontaktNamenData([...kontaktNamenData, freund.id]);
i have updated your code according to best understanding about what you are asking. with two things in count. 1. low re render and 2. DRY Clean