React项目异步加载图片接口仅页面刷新后生效是什么原因?
问题描述
我花了一周多时间查找相关问题讨论,大部分相关问题都和刷新后数据无法持久化有关,而我遇到的是未刷新时状态异常,一直没有进展。
我需要在用户登录后加载图片画廊页面,登录流程运行正常:通过reducer更新状态后从/login路由跳转到/gallery,在开发者工具中可以看到用户ID从null成功更新为有效数值。
在/gallery页面我尝试通过axios异步请求数据,采用POST请求是为了将用户ID放在请求体而非URL参数中传递。
首次登录跳转后state.images不会更新,还抛出如下错误:
"data: "Cast to string failed for value "{ user: '60fc726d827a4e3daff47619' }" (type Object) at path "user" for model "Upload"""
针对数据库模型我做过调整尝试,包括使用$type定义字段类型、将字段设置为字符串数组类型,前者直接导致页面无法加载,后者没有任何明显效果。
如果我刷新页面,所有功能都正常,图片也能成功加载;如果从画廊页面跳转到首页再返回画廊,状态也不会更新。我不确定这是异步函数结构问题、MongoDB配置问题、reducer逻辑问题、axios POST请求本身的问题还是其他原因导致的。
我查阅资料得知相关逻辑应该放在useEffect()中执行,但我尝试后依然没有解决问题。
核心相关代码
Login组件
function Login() { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const { getLoggedIn } = useContext(AuthContext); const { dispatch } = useContext(Context); const history = useHistory(); async function login(e) { e.preventDefault(); try { const { data } = await axios.post('http://localhost:3000/auth/login', { email, password }); await getLoggedIn(); dispatch({ type: 'login', payload: { user: data._id } }) window.localStorage.setItem('user', JSON.stringify(data._id)) history.push('/gallery'); } catch (err) { console.error(err); } } return (... // 其余代码省略
Image Gallery组件
const { state, dispatch } = useContext(Context); const [isLoading, setLoading] = useState(true); const [images, setImages] = useState({ images: [] }); const user = state.user; const success = async () => { try { const res = await axios.post('http://localhost:3000/auth/mine', { user }); dispatch({ type: 'fetchSuccess', payload: { images: res.data } }) setImages(res.data); } catch (err) { console.log(err.response) } } const fail = (error) => dispatch({ type: 'fetchFail', payload: { error: error.message } }); function loadImages() { dispatch({ type: 'fetchImages' }); setTimeout(async () => { try { await success(); setLoading(false) } catch (error) { await fail(error); } }, 1000); } useEffect(() => { loadImages() //eslint-disable-next-line }, []) if (isLoading) { return (<div className='loading'>...loading</div>) } else { return (... // 其余代码省略
内容的提问来源于stack exchange,提问作者Amanda Hamilton
相关产品推荐
相关产品推荐

