Wil*_*iam 6 javascript reactjs firebase-realtime-database react-hooks
快速版本:
我的最终目标是做类似下面的链接的操作,但每个异步调用Firebase时useEffect ,列表数据都是由Firebase对象内容组成的。
https://codesandbox.io/s/usage-pxfy7
问题
在下面的代码中,useEffect封装了可对Firebase进行ping操作并返回一些称为“客户端”的数据的代码。数据可以完美检索。
然后,我使用useState的两个不同实例存储该数据useState。数据存储在clientList和clientListForRender。
到目前为止,一切都很好。
现在问题开始了。
我有第三个实例useState需要一个数字。我想为文档设置一个按键事件,以便可以使用向上/向下箭头切换计数器并访问clientListForRender数组的每个值。
设置eventListener时,我无权访问该数组(大概是由于异步调用未按允许的顺序进行访问)。
我不确定如何编写能够给我想要的结果的挂钩。
谢谢。
const clientsRef = firebase.database().ref('clients');
const [clientList,setClientListState] = useState([]);
const [clientListForRender,setClientListStateForRender] = useState([]);
const [selectedIndex, updateSelectedIndex] = useState(0);
useEffect(() => {
function handleKeyPress(event,arr){
console.log(arr)
if(event.key === "ArrowDown"){
updateSelectedIndex((prev)=>{
return prev += 1
});
}
}
clientsRef.on('child_added', snapshot => {
const client = snapshot.val();
client.key = snapshot.key; // __________________________1. get firebase data
setClientListState(function(prev){
setClientListStateForRender(()=>[client,...prev]); //_______2 store data
// document.addEventListener('keydown', handleKeyPress); <---I am not sure where to put this. I have experimented and
// I decided to omit my cluttered "experiments" to protect your eyes
return[client,...prev]
});
});
},[]);
Run Code Online (Sandbox Code Playgroud)
好的,您发布的代码存在一些问题:
1)你绝对不应该在child_added监听器中添加你的键盘监听器(这意味着每次调用child_added监听器时,你都会创建一个新的监听器,导致意外的结果和内存泄漏)
2)您在 setState 更新程序函数(您提供的回调函数 setClientListState)中调用 setState,这是一种反模式,使您的代码难以遵循和理解,并且一旦组件增长,将导致意想不到的效果。如果您想根据先前的状态更新状态,请使用 useEffect 回调
3) useEffect 函数采用第二个参数,称为依赖数组。当您为其提供空数组时,这意味着您希望效果仅运行一次,这是有问题的,因为我们看到该函数依赖于clientsRef变量。(这实际上是你的问题,因为键盘侦听器具有你的clientsList的旧值,它是空数组,所以它总是返回0,当按下按键时,我在代码沙箱中解释了更多)
4)您应该从 useEffect 函数返回一个回调函数来清理您创建的效果,关闭您附加的侦听器(否则您可能会出现内存泄漏,具体取决于组件安装/卸载的数量)
好的,代码应该是这样工作的:
const clientsRef = firebase.database().ref('clients');
const [clientList, setClientListState] = useState([]);
// I don't understand why you wanted another list, so for now i only use on list
// const [clientListForRender,setClientListStateForRender] = useState([]);
const [selectedIndex, updateSelectedIndex] = useState(0);
useEffect(() => {
function handleKeyPress(event, arr) {
if (event.key === 'ArrowDown') {
updateSelectedIndex(prev => {
if (prev >= clientList.length - 1) {
return (prev = 0);
} else {
return prev + 1;
}
});
}
}
clientsRef.on('child_added', snapshot => {
const client = snapshot.val();
client.key = snapshot.key; // __________________________1. get firebase data
setClientListState(function(prev) {
return [client, ...prev];
});
});
document.addEventListener('keydown', handleKeyPress);
// here you should return a callback to clear/clean your effects
return () => {
document.removeEventListener('keydown', handleKeyPress);
clientsRef.off();
};
// Its important to add these here, or else each time your keyboard listener runs it will have the initial value of
// clientsList ([]), and so clientsList.length = 0, and so you will always updateSelectedIndex(0)
}, [clientList, clientsRef]);
//here render based on selected list as you wish
Run Code Online (Sandbox Code Playgroud)
最后,我设置了一个工作的codesandbox,它根据您提供的示例模拟数据获取https://codesandbox.io/s/usage-4sn92,我在那里添加了一些注释来帮助解释我上面所说的内容。
| 归档时间: |
|
| 查看次数: |
205 次 |
| 最近记录: |