es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

“Demasiada recursión” al actualizar parámetros (setData) en Firebase RTDB a través de setInterval y getData.

Soy un traductor de español que traduce documentos de TI. Traduzca lo siguiente al español. No traduzca el código y la salida en markdown

Soy nuevo en react native. Tengo un problema al actualizar los datos (latitud, longitud, marca de tiempo) de cada usuario (miembro) en tiempo real a la base de datos de Firebase. Obtengo bucles infinitos.

El error que tengo es “demasiada recursión”.

firebase.config.ts

const firebaseConfig = {
    ...
};

export const getCurrentLocation = (phoneNumber: number, setData: (locationParams: any) => void) => {
    const db = getDatabase();
    const reference = ref(db, 'members/' + phoneNumber);
    onValue(reference, (snapshot) => {
        const data = snapshot.val();
        setData(data);
    })
};

export const setCurrentLocation = (phoneNumber: number, latitude: number, longitude: number, timestamp: number) => {
    const db = getDatabase();
    const reference = ref(db, 'members/' + phoneNumber);
    set(reference, {
        latitude: latitude,
        longitude: longitude,
        timestamp: timestamp,
    }).then(() => console.log('setCurrentLocation to mainUser/firebase.config'));
};

const app = initializeApp(firebaseConfig);

memberList.tsx

const [userPhoneNumber, setUserPhoneNumber] = useState('0');
const members = useSelector((state: any) => state.members);

//obtener el número de teléfono del usuario
const auth = getAuth();
useEffect(() => {
    onAuthStateChanged(auth, (user) => {
        if (user) {
            setUserPhoneNumber(user.email.replace(/\D/gi, '') || '');
        } else {
            console.log('cerrado de sesión')
        }
    });
}, [])

useEffect(() => {
    const timer = setInterval(() => {
        members.map(function (el) {
            getCurrentLocation(el.phoneNumber, (locationParams: any) => {
                let timestamp = new Date().getTime() / 1000;

                setCurrentLocation(el.phoneNumber, locationParams.latitude, locationParams.longitude, timestamp)
            })
        })
    }, 10000);

    return () => clearInterval(timer);
}, []);
Tags:  , , ,

Answer

  1. Avatar for davy.ai

    El problema parece estar en el gancho useEffect en el archivo memberList.tsx. La función setInterval dentro del gancho llama repetidamente a las funciones getCurrentLocation y setCurrentLocation, lo que provoca un bucle infinito.

    Para solucionar el problema, debes pasar una matriz de dependencias al segundo argumento del gancho useEffect. Esta matriz le dirá a React cuándo volver a ejecutar el efecto. En este caso, solo queremos ejecutar el efecto una vez cuando el componente se monte. Por lo tanto, la matriz de dependencias debe estar vacía.

    Para actualizar los datos de cada miembro, debes usar el gancho useCallback para memoizar las funciones getCurrentLocation y setCurrentLocation. Esto evitará que las funciones se creen en cada renderizado.

    Aquí está el código actualizado:

    firebase.config.ts

    const firebaseConfig: object = {
        // Objeto de configuración de Firebase
    };
    
    export const getCurrentLocation = useCallback((phoneNumber: number, setData: (locationParams: any) => void): void => {
        const db: any = getDatabase();
        const reference: any = ref(db, 'members/' + phoneNumber);
        onValue(reference, (snapshot) => {
            const data: any = snapshot.val();
            setData(data);
        });
    }, []);
    
    export const setCurrentLocation = useCallback((phoneNumber: number, latitude: number, longitude: number, timestamp: number): void => {
        const db: any = getDatabase();
        const reference: any = ref(db, 'members/' + phoneNumber);
        set(reference, {
            latitude: latitude,
            longitude: longitude,
            timestamp: timestamp,
        }).then(() => console.log('setCurrentLocation to mainUser/firebase.config'));
    }, []);
    
    const app: any = initializeApp(firebaseConfig);
    

    memberList.tsx

    const [userPhoneNumber, setUserPhoneNumber] = useState<string>('0');
    const members = useSelector((state: any) => state.members);
    
    // Obtener el número de teléfono del usuario
    const auth = getAuth();
    useEffect(() => {
        onAuthStateChanged(auth, (user) => {
            if (user) {
                setUserPhoneNumber(user.email.replace(/\D/gi, '') || '');
            } else {
                console.log('Usuario desconectado')
            }
        });
    }, []);
    
    const updateMemberLocations = useCallback(() => {
        members.map(function (el: any) {
            getCurrentLocation(el.phoneNumber, (locationParams: any) => {
                const timestamp: number = new Date().getTime()/1000;
    
                setCurrentLocation(el.phoneNumber, locationParams.latitude, locationParams.longitude, timestamp)
            })
        })
    }, [members]);
    
    useEffect(() => {
        const timer = setInterval(updateMemberLocations, 10000);
    
        return () => clearInterval(timer);
    }, [updateMemberLocations]);
    

    Ten en cuenta que ahora estamos usando la función updateMemberLocations como el callback para la función setInterval. También estamos pasando [updateMemberLocations] como segundo argumento al gancho useEffect para asegurarnos de que el intervalo se configure solo una vez.

Comments are closed.