Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 反应-useState和Firebase出现问题_Javascript_Reactjs_Firebase_Functional Programming_React Hooks - Fatal编程技术网

Javascript 反应-useState和Firebase出现问题

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

我试图解决这个问题,但我没有运气

我正在使用React和“React引导”。使用
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响应的结果,并防止多次调用,直到无效为止。但请记住,这将意味着您正在使用的数据在无效之前是过时的。

我读取上述组件的方式使其变得过时