React Hooks 结合 Firebase 数据未在页面加载时显示
React Hooks in combination with Firebase data not showing on page load
我想将 React Hooks 功能与 Firebase 结合使用。但是现在设置数据后,结果仅在更新 DOM 时可见。
我当前的代码是:
import React, { useState, useEffect } from 'react';
import firebase, { getPivotFunction } from '../../firebase';
/**
* Return a styled component
*/
const ListCards = () => {
const [data, setData] = useState([]);
const userListsRef = firebase
.database()
.ref('userLists')
.child('1234d343f');
useEffect(() => {
(async function() {
try {
const response = await getPivotFunction(userListsRef, 'lists');
setData(response);
} catch (e) {
console.error(e);
}
})();
}, []);
/**
* Return all list cards
*/
return (
<ul>
{data.map(item => (
<li key={item.time}>dummy text</li>
))}
</ul>
);
};
第一次呈现页面时 'dummy text' 不会显示,只有在触发更新时才会显示。
我的目标是让 'dummy text' 在页面加载完成并且 data
长度不为 0 时出现。
在这种情况下 getPivotFunction
包含:
/** Get FireBase data based on a pivot table */
const getPivotFunction = (ref, target) => {
let dataArray = [];
ref.once('value', userInfo => {
userInfo.forEach(function(result) {
firebase
.database()
.ref(target)
.child(result.key)
.on('value', snapshot => {
dataArray.push(snapshot.val());
});
});
});
return dataArray;
};
请告诉我
Hooks 不适用于像这样的异步函数。这样的事情应该有效:
const ListCards = () => {
const [data, setData] = useState([]);
const [loaded, setLoaded] = useState(false);
...
useEffect(() => {
getPivotFunction(userListsRef, 'lists')
.then(data => { setData(data); setLoaded(true)});
}, []);
};
然后仅在 loaded
为 true
时渲染。
您的 getPivotFunction
是一个依赖于回调的异步函数,使用 async await on 不是正确的方法。相反,您需要回调
/** Get FireBase data based on a pivot table */
const getPivotFunction = (ref, target, callback) => {
const dataArray= [];
ref.once('value', userChats => {
var i = 0;
userChats.forEach(function(result) {
firebase
.database()
.ref(target)
.child(result.key)
.on('value', snapshot => {
i++;
dataArray.push(snapshot.val());
if(i === userChats.length) {
callback(dataArray)
}
});
});
});
};
并像
一样使用它
/**
* Return a styled component
*/
const ListCards = () => {
const [data, setData] = useState([]);
const userListsRef = firebase
.database()
.ref('userLists')
.child('1234d343f');
useEffect(() => {
getPivotFunction(userListsRef, 'lists', (response) => {
setData(response);
});
}, []);
/**
* Return all list cards
*/
return (
<ul>
{data.map(item => (
<li key={item.time}>dummy text</li>
))}
</ul>
);
};
我想将 React Hooks 功能与 Firebase 结合使用。但是现在设置数据后,结果仅在更新 DOM 时可见。 我当前的代码是:
import React, { useState, useEffect } from 'react';
import firebase, { getPivotFunction } from '../../firebase';
/**
* Return a styled component
*/
const ListCards = () => {
const [data, setData] = useState([]);
const userListsRef = firebase
.database()
.ref('userLists')
.child('1234d343f');
useEffect(() => {
(async function() {
try {
const response = await getPivotFunction(userListsRef, 'lists');
setData(response);
} catch (e) {
console.error(e);
}
})();
}, []);
/**
* Return all list cards
*/
return (
<ul>
{data.map(item => (
<li key={item.time}>dummy text</li>
))}
</ul>
);
};
第一次呈现页面时 'dummy text' 不会显示,只有在触发更新时才会显示。
我的目标是让 'dummy text' 在页面加载完成并且 data
长度不为 0 时出现。
在这种情况下 getPivotFunction
包含:
/** Get FireBase data based on a pivot table */
const getPivotFunction = (ref, target) => {
let dataArray = [];
ref.once('value', userInfo => {
userInfo.forEach(function(result) {
firebase
.database()
.ref(target)
.child(result.key)
.on('value', snapshot => {
dataArray.push(snapshot.val());
});
});
});
return dataArray;
};
请告诉我
Hooks 不适用于像这样的异步函数。这样的事情应该有效:
const ListCards = () => {
const [data, setData] = useState([]);
const [loaded, setLoaded] = useState(false);
...
useEffect(() => {
getPivotFunction(userListsRef, 'lists')
.then(data => { setData(data); setLoaded(true)});
}, []);
};
然后仅在 loaded
为 true
时渲染。
您的 getPivotFunction
是一个依赖于回调的异步函数,使用 async await on 不是正确的方法。相反,您需要回调
/** Get FireBase data based on a pivot table */
const getPivotFunction = (ref, target, callback) => {
const dataArray= [];
ref.once('value', userChats => {
var i = 0;
userChats.forEach(function(result) {
firebase
.database()
.ref(target)
.child(result.key)
.on('value', snapshot => {
i++;
dataArray.push(snapshot.val());
if(i === userChats.length) {
callback(dataArray)
}
});
});
});
};
并像
一样使用它/**
* Return a styled component
*/
const ListCards = () => {
const [data, setData] = useState([]);
const userListsRef = firebase
.database()
.ref('userLists')
.child('1234d343f');
useEffect(() => {
getPivotFunction(userListsRef, 'lists', (response) => {
setData(response);
});
}, []);
/**
* Return all list cards
*/
return (
<ul>
{data.map(item => (
<li key={item.time}>dummy text</li>
))}
</ul>
);
};