【问题标题】:Why does my code in React JS goes to endless loop satisfying both conditions?为什么我在 React JS 中的代码会进入满足这两个条件的无限循环?
【发布时间】:2020-03-19 17:28:34
【问题描述】:

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;

我正在尝试设置挂钩中的值,比较用户数据库中是否存在事件 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 在这两种情况下都会无休止地设置钩子值是和否。一直卡在这几个小时。

任何形式的帮助将不胜感激!!!

【问题讨论】:

  • id 在哪里定义或传递?我看到它在includes(id) 中使用,但不在代码中
  • 您不需要 else If 语句。您可以用简单的 else 替换它。因为你的 else If 与你的 if 语句完全相反
  • 这里看起来也没什么问题。需要查看更多代码。可能是别的东西。
  • 我怀疑你在 setIsFavourite() 做某事。您能否在问题中添加代码。
  • @HolyMoly 是从 param 传递的 id const id = props.match.params.id;

标签: reactjs firebase react-hooks


【解决方案1】:

只是提供了一点重构->这只是更容易阅读

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()
},[])

我不明白为什么你的代码会循环,也许我们需要更多代码,就像上面评论者提到的那样。

【讨论】:

  • 嗨,我添加了完整的相关代码。感谢重构代码。
【解决方案2】:

如果您正在更新 setIsFavourite() 中的 firebase,那么您正在创建一个将由 .onSnapshot 侦听器接收的更改。这将导致无限循环:条件触发器更改 > 侦听条件 > 条件触发器更改 > 无限循环。

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

【讨论】:

  • 嗨,我已经更新了完整的相关代码。 setIsFavourite 只是一个基于从 firebase 接收到的值设置的钩子。
  • 您的更新没有解决我的问题。你正在创造一个无限循环的变化,因为没有什么可以阻止它。您有一个监听器进行更改,更改触发监听器,触发更改,触发监听器,触发更改...只需停止使用实时监听器并切换到一次性 getter。
  • 我根据您的建议更新了代码,但仍然无法正常工作。烦人的事情是在每次渲染时,我的代码都会自动运行两个 onClick 事件。
  • 那是因为你已经这样设置了。如果你不希望它们自动运行,那么onClick={favouriteClick(props.auth.uid, id)}应该是onClick={() =&gt; favouriteClick(props.auth.uid, id)}
【解决方案3】:

你应该为这个钩子设置一个停止条件,useEffect 钩子会在你每次渲染时触发,所以你最终会改变 props 和渲染,然后触发 useEffect 改变 props 并触发 render 生命周期钩子。

你应该有类似的东西

useEffect(() => {
  // call database
},[setFavorite]) // here goes stop condition for useEffect

如果setFavorite 仍然是false,它将不会再次触发触发器,或者如果setFavorite 为假并且来自db 的请求将其设置为true,那么下次如果它再次触发useEffect 并且setFavorite 仍然是 true 然后 useEffect 不会执行。

更多详情请阅读官方文档https://reactjs.org/docs/hooks-effect.html

【讨论】:

    【解决方案4】:

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

    这导致了一个奇怪的循环。 改变

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

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

    不客气!

    【讨论】:

    • WTH 人!!!赞!!!这有效!谢啦!!这对我来说太烦人了。您能否向我解释一下区别以及为什么现在可以使用? @Daniel Duong
    • @AbhishekPokhrel 您在组件的每个渲染上都调用了 favouriteClick。通过创建箭头函数, favouriteClick 在实际单击之前不会被调用。在包装函数运行之前,函数块中的函数调用不会被执行。
    猜你喜欢
    • 1970-01-01
    • 2021-09-18
    • 1970-01-01
    • 1970-01-01
    • 2014-02-13
    • 2016-04-08
    • 2022-08-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多