Javascript 反应-useState和Firebase出现问题
我试图解决这个问题,但我没有运气 我正在使用React和“React引导”。使用Javascript 反应-useState和Firebase出现问题,javascript,reactjs,firebase,functional-programming,react-hooks,Javascript,Reactjs,Firebase,Functional Programming,React Hooks,我试图解决这个问题,但我没有运气 我正在使用React和“React引导”。使用useState从firebase获取数据,如您在下一段代码中所见。但是我也将一个模态作为组件调用,这个模态使用useState来显示和隐藏模态 export const Models = () => { const [models, setModels] = useState(null); useEffect(() => { firebase.database().r
useState
从firebase获取数据,如您在下一段代码中所见。但是我也将一个模态作为组件调用,这个模态使用useState
来显示和隐藏模态
export const Models = () => {
const [models, setModels] = useState(null);
useEffect(() => {
firebase.database().ref('Models').on('value', (snapshot) => {
setModels(snapshot.val())
});
}, []);
return models;
}
问题的结果是,当我点击url访问模式时,会显示此模式,主组件转到firebase并再次尝试获取数据。因此,如果我在模式上单击3次,我将从firebase获取3次数据
我怎样才能解决这个问题?要仅从firebase获取一次数据,而不考虑您打开模式窗口的时间
代码的另一部分
const Gallery = () => {
const [fireBaseDate, setFireBaseDate] = useState(null);
axios.post('https://us-central1-models-gallery-puq.cloudfunctions.net/date',{format:'DD/MM/YYYY'})
.then((response) => {
setFireBaseDate(response.data)
});
let content = Models();
let models = [];
const [imageModalShow, setImageModalShow] = useState(false);
const [selectedModel, setSelectedModel] = useState('');
if(content){
Object.keys(content).map((key, index) =>
models[index] = content[key]
);
models = shuffleArray(models);
console.log(models)
return(
<div className="appContentBody">
<Jumbo />
<Promotion models={models}/>
<div className="Gallery">
<h1>Galería - Under Patagonia</h1>
<Filter />
<div className="img-area">
{models.map((model, key) =>{
let myDate = new Date(model.creationDate);
let modelEndDate = new Date(myDate.setDate(myDate.getDate() + 30)).toLocaleDateString('en-GB')
if(fireBaseDate !== modelEndDate && model.active === true){
return (
<div className="img-card filterCard" key={key}>
<div className="flip-img">
<div className="flip-img-inner">
<div className="flip-img-front">
<img className="single-img card-img-top" src={model.thumbnail} alt="Model"/>
</div>
<div className="flip-img-back">
<h2>{model.certified ? 'Verificada!' : 'No Verificada'}</h2>
<p>Número: {model.contact_number}</p>
<p>Ciudad: {model.city}</p>
<p>Servicios: {model.services}</p>
</div>
</div>
</div>
<h5>{model.name}</h5>
<Button variant="danger" onClick={() => {
setImageModalShow(true)
setSelectedModel(model)}
}>
Ver
</Button>
</div>
);
}
return 0})}
</div>
<Image
show={imageModalShow}
onHide={() => setImageModalShow(false)}
model={selectedModel}
/>
</div>
<Footer />
</div>
)} else {
return (
<div className="loading">
<h1>Loading...</h1>
</div>
)}
}
export default Gallery;
const Gallery=()=>{
const[fireBaseDate,setFireBaseDate]=useState(null);
轴心柱https://us-central1-models-gallery-puq.cloudfunctions.net/date“,{格式:'DD/MM/YYYY'})
。然后((响应)=>{
setFireBaseDate(response.data)
});
让内容=模型();
让模型=[];
const[imageModalShow,setImageModalShow]=useState(false);
常量[selectedModel,setSelectedModel]=useState(“”);
如果(内容){
Object.keys(content.map)((key,index)=>
模型[索引]=内容[键]
);
型号=shuffleArray(型号);
console.log(模型)
返回(
加雷里亚-巴塔哥尼亚下
{models.map((model,key)=>{
让myDate=新日期(model.creationDate);
让modelEndDate=新日期(myDate.setDate(myDate.getDate()+30)).toLocaleDateString('en-GB'))
if(fireBaseDate!==modelEndDate&&model.active==true){
返回(
{model.certified?'Verificada!':'No Verificada'}
努梅罗:{model.contact_number}
城市:{model.city}
服务:{model.services}
{model.name}
{
setImageModalShow(真)
setSelectedModel(模型)}
}>
版本
);
}
返回0})}
setImageModalShow(假)}
模型={selectedModel}
/>
)}否则{
返回(
加载。。。
)}
}
导出默认库;
谢谢你的时间 模型是一个常规javascript函数,而不是一个功能组件。因此,这不是钩子的有效使用,也不会像预期的那样工作。请参阅上的文档 功能组件接收道具并返回JSX或其他React元素 由于没有,它基本上是重新启动并在每次父对象调用它时调用您的效果
查看您的编辑,您可能应该删除
Models
函数,并将逻辑放入库组件中。Models是常规javascript函数,而不是功能组件。因此,这不是钩子的有效使用,也不会像预期的那样工作。请参阅上的文档
功能组件接收道具并返回JSX或其他React元素
由于没有,它基本上是重新启动并在每次父对象调用它时调用您的效果
查看您的编辑,您可能应该删除Models
函数,并将逻辑放入Gallery
组件中。我阅读上述组件的方式使您看起来好像定义了一个用于从firebase获取数据的自定义挂钩
首先,我将其重命名为useFbData,并将其视为自定义挂钩,以便您可以使用并确保遵循
按照上面的方式,如果它是组件中的函数,那么每次渲染时都会触发函数,因此您描述的行为就是我所期望的
根据请求的开销/组件呈现的频率,这可能是您想要的,因为您可能不想将过时的数据返回到组件。但是,如果您觉得应该缓存来自数据库的响应,并且您有一些逻辑使该数据无效,则可以尝试以下操作:
import { useEffect, useRef } from 'react';
const useFbData = invalidationFlag => {
const data = useRef(null);
useEffect(() => {
if (!data.current || invalidationFlag) {
firebase.database().ref('Data').on('value', (snapshot) => {
data.current = snapshot.val();
});
}
}, [invalidationFlag]);
return data.current;
};
export default useFbData;
这样,在初始运行时,每次更改InvalizationFlag的值时,useFbData挂钩内的效果都会运行。如果您跟踪InvalizationFlag并根据需要进行设置,这可能会对您有所帮助
我在这里使用ref而不是state的原因是,effect钩子不会获取依赖项数组中的数据(如果使用state,这将导致它无限循环)
这将在每次调用之间保留db响应的结果,并防止多次调用,直到无效为止。但请记住,这将意味着您正在使用的数据在无效之前是过时的。我读取上述组件的方式使其变得过时