为啥我在 React JS 中的代码会进入满足这两个条件的无限循环?
Posted
技术标签:
【中文标题】为啥我在 React JS 中的代码会进入满足这两个条件的无限循环?【英文标题】: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;
【参考方案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=() => 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 在实际单击之前不会被调用。在包装函数运行之前,函数块中的函数调用不会被执行。以上是关于为啥我在 React JS 中的代码会进入满足这两个条件的无限循环?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 React 应用程序在运行“npm start”命令时会出错?
React.js 和 webpack - 为啥它不允许 var、let、const?