如何等到设置上下文值?



我正在尝试呈现一个标题。

首先,在 InnerList.js 中,我进行 API 调用,并使用来自 API 调用的数据在上下文中设置一个列表。

其次,在上下文.js中,我获取列表并将其设置为特定数据。

然后,在InnerListHeader.js中,我使用特定数据在标头中呈现。

问题:我目前收到未定义的 TypeError,因为在渲染之前未设置上下文。有没有办法在加载前通过异步或其他方式等待数据设置?

我的代码块在下面。我一直在StackOverflow和博客上查看很多问题,但无济于事。谢谢!

内部列表.js

componentDidMount() {
const { dtc_id } = this.props.match.params;
const {
setSpecificDtcCommentList,
} = this.context;
MechApiService.getSpecificDtcCommentList(dtc_id)
.then(res => 
setSpecificDtcCommentList(res)
)
}
renderSpecificDtcCommentListHeader() {
const { specificDtc = [] } = this.context;
return (
<InnerDtcCommentListItemHeader key={specificDtc.id} specificDtc={specificDtc} />
)
}

上下文.js

setSpecificDtcCommentList = (specificDtcCommentList) => {
this.setState({ specificDtcCommentList })
this.setSpecificDtc(specificDtcCommentList)
}
setSpecificDtc = (specificDtcCommentList) => {
this.setState({ specificDtc: specificDtcCommentList[0] })
}

InnerListHeader.js

render() {
const { specificDtc } = this.props;
return (
<div>
<div className="InnerDtcCommentListItemHeader__comment">
{specificDtc.dtc_id.dtc}
</div>
</div>
);
}

一般来说,您应该始终考虑变量可以在没有适当值的情况下到达渲染阶段(例如未设置(。这取决于你防止崩溃。

例如,您可以按如下方式重写代码段:

render() {
const { specificDtc } = this.props;
return (
<div>
<div className="InnerDtcCommentListItemHeader__comment">
{Boolean(specificDtc.dtc_id) && specificDtc.dtc_id.dtc}
</div>
</div>
);
}

当您进行 api 调用时,您可以在从 api 获取数据时设置加载器,一旦它在那里,您就可以显示将呈现该数据的组件。 在您的示例中,您可以添加一个新状态,该状态将像这样将 api 调用状态传递给子项

render() {
const { specificDtc, fetchingData  } = this.props;
if (fetchingData){
return <p>Loading</p>
}else{
return (
<div>
<div className="InnerDtcCommentListItemHeader__comment">
{specificDtc.dtc_id.dtc}
</div>
</div>
);
}
}
``

就我而言,我正在向Firebase调用外部API,这导致该上下文传递未定义某些值(如用户(。 所以我使用加载集来等待 API 请求完成,然后返回提供程序

import { createContext, useContext, useEffect, useState } from 'react';
import {
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
signOut,
onAuthStateChanged,
GoogleAuthProvider,
signInWithPopup,
updateProfile
} from 'firebase/auth';
import { auth } from '../firebase';
import { useNavigate } from 'react-router';
import { create_user_db, get_user_db } from 'api/UserAPI';
import { CircularProgress, LinearProgress } from '@mui/material';
import Loader from 'ui-component/Loader';
const UserContext = createContext();
export const AuthContextProvider = ({ children }) => {
const [user, setUser] = useState();
const [user_db, setUserDB] = useState();
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [loading, setLoading] = useState(true);
const navigate = useNavigate();
const createUser = async (email, password) => {
const user = await createUserWithEmailAndPassword(auth, email, password);
};
const signIn = (email, password) => {
return signInWithEmailAndPassword(auth, email, password)
.then(() => setIsAuthenticated(true))
.catch(() => setIsAuthenticated(false));
};
const googleSignIn = async () => {
const provider = new GoogleAuthProvider();
await signInWithPopup(auth, provider)
.then(() => setIsAuthenticated(true))
.catch(() => setIsAuthenticated(false));
};
const logout = () => {
setUser();
return signOut(auth).then(() => {
window.location = '/login';
});
};
const updateUserProfile = async (obj) => {
await updateProfile(auth.currentUser, obj);
return updateUser(obj);
};
const updateUser = async (user) => {
return setUser((prevState) => {
return {
...prevState,
...user
};
});
};
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, async (currentUser) => {
setLoading(true);
if (currentUser) {
const user_db = await get_user_db({ access_token: currentUser.accessToken });
setUserDB(user_db);
setUser(currentUser);
setIsAuthenticated(true);
}
setLoading(false);
});
return () => {
unsubscribe();
};
}, []);
if (loading) return <Loader />;
return (
<UserContext.Provider value={{ createUser, user, user_db, isAuthenticated, logout, signIn, googleSignIn, updateUserProfile }}>
{children}
</UserContext.Provider>
);
};
export const UserAuth = () => {
return useContext(UserContext);
};

相关内容

  • 没有找到相关文章