cor*_*ter 0 async-await reactjs firebase-hosting axios react-hooks
我是一名自学成才的开发人员,几乎完全使用原生 iOS 应用程序。对于我的一个项目,我聘请了一名 Web 开发人员来构建 React Web 应用程序(由 Firebase 托管)。他来自乌克兰,突然不得不停下来,所以我接手来完成它。因此,我无法以传统方式学习 React/HTTPS/axios/Node.js,即通过教程、练习、核心概念等缓慢学习。尽管几个月前,我还是能够完成它,一切都很好。然而,在过去的几周里,我不得不重构我的整个架构,包括创建一个新的 GCP 项目、一个新的 Firebase 项目、新的 git 存储库等,其中包括除了一些代码优化和数据模型之外的所有重新配置调整。正是在这次重组的某个时刻,我的问题出现了。我提到这一切是为了指出A)我一直严重依赖他的原创工作,尤其是在设置 Firebase Hosting 方面,B)我不太确定问题出在哪里。我 90% 确定它是用 React 实现的,但这很奇怪,因为从两个月前完成它开始,我并没有真正对异步网络调用进行任何更改,而且它按预期工作。
无论如何,在出现时,Web 应用程序请求向客户端呈现哪个视图,该视图是NotFoundView、 aReviewUserView或UserProfileView,由给定 a 的后端确定userId。问题是当UserProfileView显示时,某些原因会导致该视图无限地重新渲染。首先,在不超过两秒的时间内,它会正确显示此视图,然后非常快速地重置和重新渲染。useEffect我认为它与和/或React 钩子有关useState,尽管我不确定在哪个视图中。
非常感谢任何帮助,谢谢。
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)
}
}
Run Code Online (Sandbox Code Playgroud)
在本地调试时,这是控制台快速打印出来的内容。重复的模式可能表明了某些事情,尽管我不知道是什么。 注意:为了简单起见,我在这篇文章中重命名了一些内容,ReferralRequest.view实际上是UserProfileView.
小智 6
相反,这样做:
//After every rendering ONLY IF `prop` or `state` changes in this case `userDate always change`
useEffect(() => {
loadUserData()
}, [userData])
Run Code Online (Sandbox Code Playgroud)
做这个:
//Runs ONCE after initial rendering
useEffect(() => {
loadUserData()
}, [])
Run Code Online (Sandbox Code Playgroud)
要说为什么会这样,你应该知道 useEffect(callback, dependency) 的依赖参数。
这里是使用情况的区别
1-)未提供依赖项:
每次渲染后都会产生副作用。
例子:
useEffect(() => {
// Runs after EVERY rendering
});
Run Code Online (Sandbox Code Playgroud)
2-)空数组[]:这是你应该做的。
副作用在初始渲染后运行一次。
例子:
useEffect(() => {
// Runs ONCE after initial rendering
}, []);
Run Code Online (Sandbox Code Playgroud)
3-)有 props 或 state 值:这是你的问题。
仅当任何依赖值发生变化时,副作用才会发生。
例子:
useEffect(() => {
// Runs ONCE after initial rendering
// and after every rendering ONLY IF `prop` or `state` changes
}, [prop, state]);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
933 次 |
| 最近记录: |