我是一个自学成才的开发者,几乎完全是原生iOS应用。(由Firebase托管)。他来自乌克兰,突然不得不停下来,所以我接手完成了它。正因为如此,我一直无法传统地学习React/HTTPS/axios/Node.js,即以缓慢的速度学习教程,练习,虽然几个月前,我能够完成它,一切都很好。然而,在过去的几周里,我不得不重组我的整个架构,包括创建一个新的GCP项目,一个新的Firebase项目,新的git仓库等。其中包括所有的重新配置,除了一些代码优化和数据模型调整。正是在这个重组的某个时候,我的问题出现了。我提到这一切是为了指出**A)**我一直非常依赖他的原创作品,特别是在设置Firebase Hosting方面,**B)**我不确定问题出在哪里。我90%确定是React,但这很奇怪,因为两个月前完成异步网络调用时,我并没有对它做任何更改,它按预期工作。
无论如何,在出现时,Web应用程序请求将哪个视图呈现给客户端,这是NotFoundView
,ReviewUserView
或UserProfileView
,由后端给定userId
确定。问题是当显示UserProfileView
时,某些东西导致此视图无限重新渲染。首先,不超过两秒,它正确显示此视图,我认为这与useEffect
和/或useState
React钩子有关,尽管我不确定是在哪个视图中。
任何帮助都非常感谢,谢谢。
export enum ViewState {
UserProfile = 'UserProfile',
ReviewForm = 'ReviewForm',
NotFound = 'NotFound'
}
....................................................
export class ApiHandler {
// Returns a ViewState enum case for main view routing
public static requestViewState(id: string): Promise<AxiosResponse<ViewState>> {
console.log('REQUESTING VIEW STATE')
return axios.get(`${API_URL}/user/${id}/view-state`)
}
// Returns the requested user's profile data + other info
public static requestUserData(id: string): Promise<AxiosResponse<UserData>> {
console.log('REQUESTING USER DATA')
return axios.get(`${API_URL}/user/${id}`)
}
// More API calls ...
}
....................................................
export function RoutingView(props: RouteComponentProps<RoutingViewProps>) {
const userId = props.match.params.id
const [viewState, setViewState] = useState<ViewState>()
const [showError, setShowError] = useState<boolean>()
const [showLoader, setShowLoader] = useState<boolean>(true)
useEffect(() => {
loadViewState()
}, [])
if (showLoader) {
return <PageLoader />
}
if (showError) {
return <FailedToLoad />
}
switch (viewState) {
case ViewState.UserProfile:
return <UserProfileView id={userId} />
case ViewState.ReviewForm:
return <ReviewUserView id={userId} />
default:
return <NotFoundView />
}
async function loadViewState(): Promise<void> {
setShowLoader(true)
try {
const viewStateData = await ApiHandler.requestViewState(userId)
setViewState(viewStateData.data)
} catch (error) {
console.log(error)
setShowError(true)
}
setShowLoader(false)
}
}
....................................................
export default function UserProfileView(props: UserProfileProps) {
console.log('INITIALIZED USERPROFILEVIEW')
const userId = props.id
const [userData, setUserData] = useState<UserData>()
const [showLoader, setShowLoader] = useState<boolean>(false)
const [service, setService] = useState<Service | null>()
const [loadFailed, setLoadFailed] = useState<boolean>()
useEffect(() => {
if (userData?.user) {
const user = userData?.user
document.title = `${user?.firstName} ${user?.lastName}`
}
}, [userData])
useEffect(() => {
loadUserData()
}, [userData])
if (loadFailed) {
return <FailedToLoad />
}
return <div>
{showLoader ? <PageLoader/> : ''}
{
userData?.user && <div className={service ? styles.Hidden : ''}>
<UserInfo
user={userData?.user}
services={userData?.services}
selectedService={(service) => setService(service)}
submitted={userData?.hasSubmitted}
/>
</div>
}
// More view components ...
</div>
async function loadUserData(): Promise<void> {
setShowLoader(true)
try {
const res = await ApiHandler.requestUserData(userId)
setUserData(res.data as UserData)
} catch (error) {
console.log(error)
setLoadFailed(true)
}
setShowLoader(false)
}
}
当在本地调试时,这是控制台快速输出的内容。重复的模式可能表明了一些东西,尽管我不知道是什么。**注意:**为了简单起见,我在这篇文章中重命名了一些东西,ReferralRequest.view
实际上是UserProfileView
。
4条答案
按热度按时间edqdpe6u1#
而是这样做:
执行以下操作:
要说明原因,您应该知道useEffect的dependencies参数(callback,dependencies)。
这里使用的不同情况
1-)未提供依赖:
副作用在每次渲染之后运行。
示例:
2-)**一个空数组[]:**这是你应该做的。
副作用在初始渲染后运行一次。
示例:
3-)**有props或state值:**这是你的问题。
副作用仅在任何dependency值更改时运行。
示例:
wydwbb8l2#
更改代码
至
修复了无限获取,useEffect方法依赖于userData中的任何更改。每次获取都会更改该变量,从而导致无限循环。添加if null检查将停止另一次数据获取。
czq61nw13#
这是因为这段代码
问题是
useEffect
的第二个参数是效应所依赖的变量。如果这些变量中的任何一个在
useEffect
的回调中被改变,那么它将被再次调用,通过加载这些数据生成一个无限循环,通过setUserData
查看它们,数据被改变,loadUserData
再次被调用,等等。aij0ehis4#
要解决无限循环,请更改以下代码:
这段代码:
不要将状态作为参数传入,而是传入设置状态的方法。