React路由场景下基于HOC实现组件数据复用的问题
解决React Router中HOC未触发数据请求的问题
这个问题我之前也碰到过,核心问题在于你没有让路由渲染被HOC包裹后的组件,而是直接使用了原组件,导致HOC的逻辑(比如数据请求)根本没机会执行。下面给你一步步的解决方案:
1. 编写通用的获取博客数据的HOC
首先我们要实现一个HOC,它负责从后端获取数据,然后把数据、加载状态、错误状态等作为props传递给被包裹的组件。这里用函数组件+hooks实现(如果是类组件可以用componentDidMount替代useEffect):
import { useEffect, useState } from 'react'; import { useParams } from 'react-router-dom'; // 定义HOC:接收需要数据的组件作为参数 const withBlogData = (WrappedComponent) => { return (props) => { const { postId } = useParams(); // 从路由获取文章ID参数 const [postData, setPostData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchPostData = async () => { try { setLoading(true); // 替换成你的实际后端API地址 const response = await fetch(`/api/posts/${postId}`); if (!response.ok) throw new Error('获取文章数据失败'); const data = await response.json(); setPostData(data); } catch (err) { setError(err.message); } finally { setLoading(false); } }; // 当postId存在时才发起请求 if (postId) { fetchPostData(); } }, [postId]); // 将数据和状态传递给被包裹的组件,同时保留原props return ( <WrappedComponent {...props} postData={postData} loading={loading} error={error} /> ); }; };
2. 用HOC包裹你的目标组件
接下来把BlogPost和EditableBlogPost组件用这个HOC包裹,得到新的具备数据请求能力的组件:
// 普通的BlogPost组件,接收HOC传递的props const BlogPost = ({ postData, loading, error }) => { if (loading) return <div>加载中...</div>; if (error) return <div>出错了:{error}</div>; if (!postData) return null; return ( <article> <h1>{postData.title}</h1> <div className="post-content">{postData.content}</div> </article> ); }; // 用HOC包装BlogPost const BlogPostWithData = withBlogData(BlogPost); // 同样处理EditableBlogPost const EditableBlogPost = ({ postData, loading, error }) => { if (loading) return <div>加载中...</div>; if (error) return <div>出错了:{error}</div>; if (!postData) return null; return ( <div className="edit-post"> <h1>编辑文章:{postData.title}</h1> <input type="text" defaultValue={postData.title} /> <textarea defaultValue={postData.content} rows={10} /> </div> ); }; const EditableBlogPostWithData = withBlogData(EditableBlogPost);
3. 在路由中使用被HOC包裹后的组件
现在把路由配置里的原组件替换成我们刚刚包装好的组件,这样路由渲染的时候会先执行HOC的逻辑,完成数据请求后再渲染目标组件:
import { Routes, Route } from 'react-router-dom'; function App() { return ( <Routes> {/* 使用带数据请求的组件 */} <Route path="/post/:postId" element={<BlogPostWithData />} /> <Route path="/post/:postId/edit" element={<EditableBlogPostWithData />} /> </Routes> ); }
为什么原来的方式不生效?
你之前直接把BlogPost或者EditableBlogPost传给路由的element属性,相当于直接渲染了原组件,HOC根本没有被调用,它内部的数据请求逻辑自然不会执行。只有让路由渲染被HOC包裹后的组件,HOC的代码才会被执行,进而完成数据请求并把数据传递给原组件。
内容的提问来源于stack exchange,提问作者Matt Pengelly
相关产品推荐
相关产品推荐

