Ваша проблема в том, что по умолчанию useEffect()
будет запускаться каждый раз, когда ваш компонент рендерится. Происходит то, что ваш эффект вызывает изменение в компоненте, которое запускает повторный запуск эффекта, и в результате вы получаете нечто, приближающееся к бесконечному циклу.
К счастью, реакция дает нам некоторый контроль над тем, когда запускать ловушку эффекта в виде массива, который вы можете передать в качестве дополнительного параметра. В вашем случае, например:
useEffect(() => {
let clientsRef = firebase.database().ref('clients');
clientsRef.on('child_added', snapshot => {
const client = snapshot.val();
client.key = snapshot.key;
setState([...state, client])
});
}, []);//An empty array here means this will run only once.
Массив сообщает, какие свойства нужно посмотреть. Всякий раз, когда одно из этих свойств изменяется, оно запускает функцию очистки и повторно запускает эффект. Если вы отправите пустой массив, он будет запущен только один раз (поскольку нет свойств для просмотра). Например, если вы добавите [userId]
, эффект будет запускаться каждый раз, когда изменяется переменная userId
.
Говоря о функции очистки, вы не возвращаете ее в свой эффект-хук. Я не достаточно знаком с firebase, чтобы знать, нужно ли что-либо очищать при уничтожении компонента (например, удалить привязку события child_added). Хорошей практикой будет возвращать метод как последнюю часть вашего эффекта использования. Окончательный код будет выглядеть примерно так:
useEffect(() => {
let clientsRef = firebase.database().ref('clients');
clientsRef.on('child_added', snapshot => {
const client = snapshot.val();
client.key = snapshot.key;
setState([...state, client])
});
return () => { /* CLEANUP CODE HERE */ };
}, []);//An empty array here means this will run only once.