为什么我在React JS中的代码会陷入无限循环,同时满足这两个条件?

时间:2019-11-24 04:16:36

标签: reactjs firebase react-hooks

import React, { useEffect, useState } from "react";
import { connect } from "react-redux";
import { Redirect } from "react-router-dom";
import firebase from '../../config/firebaseConfig'

import SingleEventSummary from './SingleEventSummary'

import { getEvent } from "./../../store/actions/eventActions";

import "./SingleEvent.css";
const SingleEvent = props => {
	const id = props.match.params.id;

	const [eventItem, seteventItem] = useState([]);
	const [isFavourite, setIsFavourite] = useState("no");

	//getting specific event
	useEffect(() => {

		const db = firebase.firestore().collection('newEvents').doc(id)

		db.onSnapshot(snapshot => {
			seteventItem(snapshot.data())
		})
	}, [id])

	//checking if there is favourite
	useEffect(() => {
		const db = firebase.firestore().collection('users').doc(props.auth.uid)
	  
		db.get().then(snapshot => {
		  const data = snapshot.data()
		  const faves = data && snapshot.data().favorites || []
	  
		  faves.includes(id) ? setIsFavourite("yes") : setIsFavourite("no")
		},(error) => console.error(error))
	  },[isFavourite])
    

	//setting as favourites
	const favouriteClick = (uid, eid) => {
		debugger;
		let initFav = firebase.firestore().collection('users').doc(uid);
		initFav.get().then(snapshot => {
			const arrayUnion = firebase.firestore.FieldValue.arrayUnion(eid);
			initFav.update({
				favorites: arrayUnion,
			});
			setIsFavourite("yes")
		},(error) => console.error(error))
	}

	//remove favourites
	const removeFavourite = () => {
		debugger;
		const initFavo = firebase.firestore().collection('users').doc(props.auth.uid);
		initFavo.get().then(snapshot => {
			if (snapshot.data().favorites) {
				if (snapshot.data().favorites.includes(id)) {
					let data = snapshot.data().favorites.filter(el => el != id )
					initFavo.update({
						favorites: data,
					});
					setIsFavourite("no")
				}
			}
		},(error) => console.error(error))
		return () => initFavo()
	}

	console.log("wtf is this shit", isFavourite)
  
	if (isFavourite == "no") {
		return (
			<main className="single-event_main">
				<a className="waves-effect waves-light btn" onClick={favouriteClick(props.auth.uid, id)}>Add As Favourites!!</a>
			</main>
		);
}
	 else {
		return (
			<main className="single-event_main">
				<div className="row">
					<div className="col s6">
						<a className="waves-effect waves-light btn" disabled>Favourite Event!!</a>
					</div>
					<div className="col s6">
						<a className="waves-effect waves-light btn" onClick={removeFavourite}>Remove From Favourites!!</a>
					</div>
				</div>
			</main>
		);
	} 
};

export default SingleEvent;

我正在尝试在hook中设置值,比较事件ID是否存在于用户的数据库中(如果他/她已将该事件设置为收藏)。

....
const [isFavourite, setIsFavourite] = useState("no");

//checking if there is favourite
useEffect(() => {
    debugger;
    const db = firebase.firestore().collection('users').doc(props.auth.uid)
    db.onSnapshot(snapshot => {
        debugger;
        if(snapshot.data()) {
            if (snapshot.data().favorites) {
                if (snapshot.data().favorites.includes(id)) {
                    setIsFavourite("yes")
                }
                else if(!snapshot.data().favorites.includes(id)){
                    setIsFavourite("no")
                }
            }
        }
    }, (error) => console.error(error));
    return () => db()
},[])
....

问题是,react进入这两个条件,不断地将钩子值设置为yes和no。在这个小时被困住了。

任何帮助将不胜感激!!!

4 个答案:

答案 0 :(得分:0)

jus提供了一些重构->这一点更容易阅读

useEffect(() => {
  const db = firebase.firestore().collection('users').doc(props.auth.uid)

  db.onSnapshot(snapshot => {
    const data = snapshot.data()
    const faves = data && snapshot.data().favorites || []

    faves.includes(id) ? setIsFavourite("yes") : setIsFavourite("no")
  },(error) => console.error(error))

  return () => db()
},[])

我不明白为什么您的代码会循环,也许我们需要更多的代码,如上面的注释者所述。

答案 1 :(得分:0)

如果您要在setIsFavourite()中更新Firebase,那么您正在创建一个将由.onSnapshot侦听器获取的更改。这将导致无休止的循环:条件触发条件变化>监听条件>条件触发条件变化>广告无限。

您要么需要从.onSnapshot切换到一次性.get侦听器,要么需要添加条件以防止在这种情况下传播更改。此自定义条件将特定于您的实现,除非您展示使用更多的代码并帮助我们了解您要实现的目标(尽管这应该是一个单独的问题),否则我们无法真正提供帮助。所以我怀疑在这种情况下是前者。

答案 2 :(得分:0)

您应该为此钩子设置一个停止条件,useEffect钩子在您每次渲染某物时都会被触发,因此您最终会更改道具并渲染,然后触发useEffect,后者会改变道具并触发{{ 1}}生命周期挂钩。

您应该有类似的东西

render

如果useEffect(() => { // call database },[setFavorite]) // here goes stop condition for useEffect 仍为setFavorite,它将不会再次触发,或者如果false为false并且来自db的请求将其设置为setFavorite,则下次您会再次触发true,而useEffect仍然是setFavorite,那么true将不会执行。

有关更多详细信息,请阅读官方文档https://reactjs.org/docs/hooks-effect.html

答案 3 :(得分:0)

现在您已经向我们展示了更多代码。我可以很有信心地说,这是因为您在“添加为收藏夹”按钮的onClick中调用了收藏夹单击。

这引起了怪异的循环。 更改

onClick={favouriteClick(props.auth.uid, id)

onClick={() => favouriteClick(props.auth.uid, id)

不客气!