Поскольку мой комментарий решил эту проблему, вот официальный ответ:
Причина, по которой ваше состояние всегда объединяется, состоит в том, что ваша переменная fetchedTasks
объявляется только один раз, когда ловушка useEffect
запускается onMount. После этого каждый раз, когда ваша база данных firebase обновляет новые значения и вы вызываете fetchedTasks.push(...)
, вы нажимаете на один и тот же «старый» массив. Поэтому ваш список становится все длиннее и длиннее.
Одним из решений было бы просто повторно объявить fetchedTasks
или установить его обратно в пустой массив.
const [tasks, setTasks] = useState([]);
useEffect(() => {
const ref = props.firebase.db.ref('users/1zfRCHmD4MVjJj7L884LL4TMwAH3');
const listener = ref.on('value', snapshot => {
const fetchedTasks = [];
snapshot.forEach(childSnapshot => {
const key = childSnapshot.key;
const data = childSnapshot.val();
fetchedTasks.push({ id: key, ...data });
});
setTasks(fetchedTasks);
});
return () => ref.off('value', listener);
}, [props.firebase.db]);
Другим было бывместо этого использовать .map
и использовать возвращаемое значение для setTasks
. Я думаю, что это было бы моим предпочтением:
const [tasks, setTasks] = useState([]);
useEffect(() => {
const ref = props.firebase.db.ref('users/1zfRCHmD4MVjJj7L884LL4TMwAH3');
const listener = ref.on('value', snapshot => {
const fetchedTasks = snapshot.map(childSnapshot => {
const key = childSnapshot.key;
const data = childSnapshot.val();
return { id: key, ...data };
});
setTasks(fetchedTasks);
});
return () => ref.off('value', listener);
}, [props.firebase.db]);
, также обратите внимание, что вам нужно будет передать props.firebase.db
в ваш массив зависимостей, чтобы избавиться от предупреждения eslint. Ссылка на props.firebase.db
никогда не должна изменяться, поэтому ее следует сохранить, чтобы объявить ее в массиве зависимостей.