英文:
how do I update my state from an API call side Effect in React native?
问题
我有一段代码,使用 useEffect 钩子从 Firebase 存储获取文件列表的元数据,然而,在 useEffect 中更新我的状态似乎有困难。我已经尝试了 async/await 模式来解决 setState 的异步性质,但没有太大成功。
我的伪代码片段如下:
const [someData, setSomeData] = useState([]);
const dataArray = [];
useFocusEffect(
useCallback(() => {
async function getData() {
const result = await listAll(storageRef);
await result.items.map(async (itemRef) => {
const Metadata = await getMetadata(itemRef);
await dataArray.push({ 'name': Metadata.name });
await console.log(dataArray); // 在每次迭代中显示数组被填充
});
await setSomeData(dataArray);
await console.log(someData); // 我期望它打印出更新后的状态,但实际上打印一个空数组
}
getData();
}, [])
);
此外,我似乎也无法在代码的返回部分访问状态:
return (
{someData.map(({ item }) => {
return (
<View><Text>{item.name}</Text></View>
);
})}
);
根据我所看到的,这似乎没有输出任何内容。
在我的方法中漏掉了什么?
提前感谢。
英文:
I have a piece of code that gets Metadata of a list of files from Firebase storage using the useEffect hook. I however, struggle to update my state within this useEffect. I have used the async/await pattern to mitigate the asynchronous nature of setState without much success.
My snippet in pseudocode:
const [someData,setSomeData]=useState([])
const dataArray=[]
useFocusEffect(
useCallback(()=>{
async function getData(){
const result=await listAll(storageRef);
await result.items.map(async (itemRef)=>{
const Metadata=await getMetadata(itemRef);
await dataArray.push({'name':Metadata.name})
await console.log(dataArray) //shows the array being populated on each iteration
})
await setSomeData(dataArray);
await console.log(someData) // I'm expecting it to print an updated state, prints an empty array instead
}
getData()
},[])
)
I also cannot seem to access the state in the return part of my code:
return(
{someData.map(({item})=>{
return(
<View><Text>{item.name}</Text><View>)})
outputs nothing as far as I can tell.
What am I missing in my approach?
Thanks in advance
答案1
得分: 0
- setSomeData()不返回Promise,因此无法等待。
- dataArray需要在getData()内部作用域中。
- getData封闭了someData,因此它永远不会获取到更新的值,因为该函数调用是指向先前的值。
- 可能更容易使用一个与React Native兼容的异步数据库。
英文:
- setSomeData() does not return a promise, thus cannot be awaited.
- dataArray needs to be scoped inside getData()
- getData closes around someData, so it will never get the updated value
as that function call is referring to the previous value - it might be easier to use a react native compatible async data library
答案2
得分: 0
dataArray
在每次渲染时都被重新初始化为 []
,然后你将 someData
设置为 dataArray
,实际上是将 someData
设置为空数组。我认为如果你将异步映射包装在 Promise.all
中,那么可以使 dataArray
作用域限定在你的 getData
函数中:
const fetchData = useCallback(() => {
async function getData() {
const result = await listAll(storageRef);
const dataArray = await Promise.all(
result.items.map(async (itemRef) => {
const Metadata = await getMetadata(itemRef);
console.log(Metadata);
return { name: Metadata.name };
})
);
console.log("dataArray:\n", dataArray);
setSomeData(dataArray);
// 即使你等待 setSomeData,someData 也不会是更新后的值。
/* 如果你想查看 someData 的变化,可以这样做
useEffect(() => {
console.log(someData)
}, [someData])
*/
}
getData();
}, []);
useFocusEffect(fetchData);
英文:
dataArray
is being re-initialized to []
every render, and then you are setting someData
to dataArray
, effectively setting someData
to an empty array. I think if you wrap your async map in a Promise.all then you can have dataArray scoped to your getData
function:
const fetchData = useCallback(() => {
async function getData() {
const result = await listAll(storageRef);
const dataArray = await Promise.all(
result.items.map(async (itemRef) => {
const Metadata = await getMetadata(itemRef);
console.log(Metadata);
return { name: Metadata.name };
})
);
console.log("dataArray:\n", dataArray);
setSomeData(dataArray);
// even if you await setSomeData, someData wont be the the updated value.
/* If you want to see someData changes do
useEffect(()=>{
console.log(someData)
},[someData])
*/
}
getData();
}, []);
useFocusEffect(fetchData);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论