React+Firebase登录用户内容的社交媒体分享最佳实践
我是React新手,开发的React应用里,登录用户拥有由文本和base64格式图片组成的内容,这些内容需要登录才能访问,存储在Firebase中——以Firebase生成的user.id作为分类,每条内容包含我生成的UUID、base64图片及文本。
主页面会列出当前登录用户的所有内容,我想给每条内容加分享按钮(比如分享到Facebook)。目前我通过React Router的Link组件把story对象通过state传递到/loadedstory页面:
arrayOfStories.map((story) => ( // ...其他代码 <Link className="logo-container" to='/loadedstory' state={story}> // ... ))
在loadedstory.component.jsx中通过useLocation()获取state并渲染内容:
const LoadedStory = () => { const {state} = useLocation(); // ...其他代码 return ( <> <div> { state && state.uuid ? ( <> <div className="story-content"> <img alt="Your content!" src={`data:image/png;base64,${state.image}`} className='resize-image' /> </div> <div className="story-content"> <p><span className='stroke'>{state.storyText}</span></p> </div> // ...其他内容 </> ): (<div></div>)} </div> // ...其他代码 </> ) }
但这样分享/loadedstory链接时,因为缺少useLocation的state,无法加载内容。请问开发这类登录上下文内可分享内容的最佳实践是什么?
我考虑使用/loadedstory/:uuid的路由,通过UUID查询Firebase,但Firebase是按user.id分类存储内容的,是否需要遍历所有用户查找该UUID?这是否是正确的实现方式?
解决方案
1. 改用带UUID的路由是正确方向
当前通过state传递数据的方式仅适合应用内部跳转,分享链接时state不会被携带,所以必须用路由参数(UUID)+ 后端查询的方案,也就是/loadedstory/:uuid这种形式。
2. 优化Firebase数据结构,避免遍历所有用户
不需要遍历所有用户查找UUID,调整数据结构就能实现高效查询:
- 方案一:新增全局映射集合
在Firebase中创建storiesByUuid集合,每个文档ID就是故事的UUID,文档内容包含对应的userId和故事核心数据(storyText、image等)。通过UUID直接查询这个集合,就能快速拿到所属用户ID,再去对应用户的故事集合验证权限(也可以直接在这个集合存储完整数据,同时通过Firebase规则确保只有对应用户能写入)。
示例数据结构:storiesByUuid/ {uuid}/ userId: "xxx123", storyText: "xxx", image: "base64字符串" users/ {userId}/ stories/ {uuid}/ // 原故事数据 - 方案二:给故事文档添加uuid字段并创建复合索引
如果不想新增集合,可以在每个用户的stories文档里添加uuid字段,然后使用Firebase的集合组查询:
注意:需要在Firebase控制台创建对应的集合组索引,否则查询会报错。该方案无需额外维护映射数据,但查询效率略低于第一种。// 查询所有用户stories中uuid匹配的文档 const storyRef = db.collectionGroup('stories').where('uuid', '==', targetUuid);
3. 组件加载与权限验证逻辑
在LoadedStory组件中:
- 通过
useParams()获取路由中的UUID:const { uuid } = useParams(); - 根据UUID查询Firebase数据(二选一上述方案)
- 验证当前登录用户权限:
- 方案一:拿到查询结果中的
userId,和当前登录用户的user.id对比,一致才渲染内容 - 方案二:查询结果返回后,检查文档所属的用户ID是否和当前登录用户匹配
- 方案一:拿到查询结果中的
- 处理加载状态与无权限场景:比如显示加载提示、无权限访问提示等
4. 分享逻辑
生成带UUID的链接(如/loadedstory/abc123),用户分享该链接后,打开链接的用户需先登录,组件会自动通过UUID查询数据并校验权限,符合条件则渲染内容。
内容的提问来源于stack exchange,提问作者Rodrigo Camargo

