React根据用户输入动态获取Firestore视频字段的实现问题
问题描述
正在开发用于展示龙与地下城(DnD)动态视频地图的React应用,用户通过下拉选择框完成选项选择后,视频播放器需要从存储视频资源的Firebase Firestore数据库拉取对应视频文件播放。
现有代码如下:
const Streamplayer = ({vidSelection}) => { //vidSelection是下拉选择框返回的字符串类型选中值 const [links, setLinks] = useState([]) console.log(vidSelection); useEffect(() => { getLinks() }, []) useEffect(() => { console.log(links) }, [links]) function getLinks(){ const vidRef = collection(db, 'links'); getDocs(vidRef).then(response => { console.log(response.docs) const lnks = response.docs.map(doc => ({ data: doc.data(), id: doc.id, })) setLinks(lnks) }).catch(error => console.log(error.message)); } function getVid(){ const toReturn = links.map((link) => link.data.vidSelection);//这里需要根据输入动态返回对应字段 console.log(toReturn) return toReturn; } return ( <video controls={false} autoPlay muted loop className="Video" key={getVid()} > <source src={getVid()} type="video/mp4" /> </video> ) } export default Streamplayer
当前getVid()方法的逻辑无法正常工作:需要读取Firestorelinks集合存储的数据,根据用户选中值动态返回对应字段——比如用户选择名为"Grotto"的地图时,需要读取link.data.grotto字段的视频地址,但vidSelection是字符串变量,无法直接通过点语法嵌入属性访问路径。
解决方法
JS中如果要通过字符串变量访问对象属性,不能用点语法,直接换方括号取值语法就行:对象[存属性名的变量]。比如vidSelection的值是字符串"Grotto"时,link.data[vidSelection]就完全等价于link.data.grotto,这就是需要的动态属性读取效果。
另外原有代码还有几个逻辑bug要一起修正:
getVid()里用map返回的是数组,video标签的src只接收单个字符串地址,传数组会播放失败- 数据还没拉取完成、或者选中项没有对应地址时要做兜底,避免空值报错
- 视频的
key直接绑定当前播放地址就行,地址变化时会自动触发视频重新加载,不需要反复调用getVid()
修正后的可运行代码:
import { useState, useEffect, useMemo } from 'react' import { collection, getDocs } from 'firebase/firestore' import { db } from './your-firebase-config-path' // 替换为你自己的Firebase配置引入路径 const Streamplayer = ({vidSelection}) => { const [links, setLinks] = useState([]) // 组件挂载时拉取一次所有视频地址配置 useEffect(() => { const vidRef = collection(db, 'links'); getDocs(vidRef).then(response => { const lnks = response.docs.map(doc => ({ data: doc.data(), id: doc.id, })) setLinks(lnks) }).catch(error => console.log(error.message)); }, []) // 计算当前要播放的视频地址,依赖links和选中值自动更新 const currentVidSrc = useMemo(() => { if (!links.length) return '' // 若links集合只有一条存全量地图地址的配置文档,直接取第一条即可 const linkConfig = links[0].data // 用方括号语法读取变量对应的属性,无匹配时返回空 return linkConfig[vidSelection] || '' }, [links, vidSelection]) // 地址未加载完成时返回兜底提示 if (!currentVidSrc) return <div>视频加载中...</div> return ( <video controls={false} autoPlay muted loop className="Video" key={currentVidSrc} > <source src={currentVidSrc} type="video/mp4" /> </video> ) } export default Streamplayer
如果你的links集合是每个地图存一条独立文档,只需要调整currentVidSrc的查找逻辑即可,核心的动态属性访问还是用方括号语法。
内容的提问来源于stack exchange,提问作者Meli497
相关产品推荐
相关产品推荐

