无法在异步函数中设置上下文?
Can't set Context in async function?
好吧,请对我客气点,我对 React Native 还很陌生,但我正在使用 Context 来管理我的 React Native 项目中的一些状态。这是我被卡住的地方的例子
在功能组件的顶部我有这个...
import DataContext from "../../contexts/DataContext";
import AsyncStorage from "@react-native-community/async-storage";
const AccountHomepageScreen = ({navigation}) => {
const { data, updateInfo} = useContext(DataContext);
const getUserFromAsync = async () => {
try {
const value = await AsyncStorage.getItem('user_id');
if(value !== null) {
//shows user_id in Alert no problem
alert(value);
//but this does not work?!?!
updateInfo('userId', value);
}
} catch(e) {
// error reading value
return false;
}
}
}
useEffect(() => {
getUserFromAsync();
}, []);
在上下文文件 updateInfo 中执行以下操作
import React, { useState } from 'react';
const DataContext = React.createContext();
export const DataProvider = ({ children }) => {
const [info, setInfo] = useState({
userId: '',
textText: 'Connected!!!',
availableBusinesses : [],
getBusinessesError: ''
});
const updateInfo = (field, val) => {
setInfo({
...info, [field]: val
});
};
return (
<DataContext.Provider value={{
data: {info},
updateInfo
}}>
{children}
</DataContext.Provider>
);
};
export default DataContext;
我猜您可能正试图通过 updateInfo
函数更新组件上的某些内容。
在那种情况下,这完全取决于您在哪里调用 getUserFromAsync
函数。
如果您想在 AccountHomepageScreen
加载后立即调用它,那么您可以使用 hook
(查看 hooks 文档 here)。
使用 useEffect
将确保仅当组件在屏幕上呈现时才执行您的代码,因此该函数实际上会影响布局:
import { useContext, useEffect } from 'react'; // Import it where you're already importing useContext
import DataContext from "../../contexts/DataContext";
import AsyncStorage from "@react-native-community/async-storage";
const AccountHomepageScreen = ({ navigation }) => {
const { data, updateInfo } = useContext(DataContext);
// Calling the hook
useEffect(() => {
getUserFromAsync();
});
const getUserFromAsync = async () => {
try {
const value = await AsyncStorage.getItem("user_id");
if (value !== null) {
//shows user_id in Alert no problem
alert(value);
// you should be able to call the updateInfo function now
updateInfo("userId", value);
}
} catch (e) {
// error reading value
return false;
}
};
};
const updateInfo = (field, val) => {
setInfo(info => ({
...info, [field]: val
}));
};
这是一段神奇的代码。试试它是否能解决您的问题 ;-)
展开
我在 React 新手中看到过很多次这种错误。这是经典的 陈旧关闭 问题。
所以updateInfo
的闭包捕获了info
(后来在...info
中使用),然后getUserFromAsync
的闭包捕获了updateInfo
,最后 useEffect
的回调捕获 getUserFromAsync
.
现在因为 useEffect
的 deplist 是空的,它的回调闭包永远不会更新,它停留在有史以来创建的第一个快照。因此,从创建后的第一个状态更改开始,该闭包将成为陈旧的闭包,也就是“不同步”。
而且由于上面提到的闭包链,整个链都停滞了,从调用点useEffect
回调开始。因此更新的 info
值不会通过 setState({ ...info })
调用反映...
除非您从一开始就避免 capturing/snapshoting 行为!魔术代码就是这样做的。它避免通过闭包捕获来引用 info
,而是从
提供的回调函数参数中获取该值
setState(info => ...)
虽然闭合链仍然是 stale
,但它没有造成真正的伤害,因为它没有引用任何外部值。 setState
将确保 info
参数始终设置为最新状态值。
好吧,请对我客气点,我对 React Native 还很陌生,但我正在使用 Context 来管理我的 React Native 项目中的一些状态。这是我被卡住的地方的例子
在功能组件的顶部我有这个...
import DataContext from "../../contexts/DataContext";
import AsyncStorage from "@react-native-community/async-storage";
const AccountHomepageScreen = ({navigation}) => {
const { data, updateInfo} = useContext(DataContext);
const getUserFromAsync = async () => {
try {
const value = await AsyncStorage.getItem('user_id');
if(value !== null) {
//shows user_id in Alert no problem
alert(value);
//but this does not work?!?!
updateInfo('userId', value);
}
} catch(e) {
// error reading value
return false;
}
}
}
useEffect(() => {
getUserFromAsync();
}, []);
在上下文文件 updateInfo 中执行以下操作
import React, { useState } from 'react';
const DataContext = React.createContext();
export const DataProvider = ({ children }) => {
const [info, setInfo] = useState({
userId: '',
textText: 'Connected!!!',
availableBusinesses : [],
getBusinessesError: ''
});
const updateInfo = (field, val) => {
setInfo({
...info, [field]: val
});
};
return (
<DataContext.Provider value={{
data: {info},
updateInfo
}}>
{children}
</DataContext.Provider>
);
};
export default DataContext;
我猜您可能正试图通过 updateInfo
函数更新组件上的某些内容。
在那种情况下,这完全取决于您在哪里调用 getUserFromAsync
函数。
如果您想在 AccountHomepageScreen
加载后立即调用它,那么您可以使用 hook
(查看 hooks 文档 here)。
使用 useEffect
将确保仅当组件在屏幕上呈现时才执行您的代码,因此该函数实际上会影响布局:
import { useContext, useEffect } from 'react'; // Import it where you're already importing useContext
import DataContext from "../../contexts/DataContext";
import AsyncStorage from "@react-native-community/async-storage";
const AccountHomepageScreen = ({ navigation }) => {
const { data, updateInfo } = useContext(DataContext);
// Calling the hook
useEffect(() => {
getUserFromAsync();
});
const getUserFromAsync = async () => {
try {
const value = await AsyncStorage.getItem("user_id");
if (value !== null) {
//shows user_id in Alert no problem
alert(value);
// you should be able to call the updateInfo function now
updateInfo("userId", value);
}
} catch (e) {
// error reading value
return false;
}
};
};
const updateInfo = (field, val) => {
setInfo(info => ({
...info, [field]: val
}));
};
这是一段神奇的代码。试试它是否能解决您的问题 ;-)
展开
我在 React 新手中看到过很多次这种错误。这是经典的 陈旧关闭 问题。
所以updateInfo
的闭包捕获了info
(后来在...info
中使用),然后getUserFromAsync
的闭包捕获了updateInfo
,最后 useEffect
的回调捕获 getUserFromAsync
.
现在因为 useEffect
的 deplist 是空的,它的回调闭包永远不会更新,它停留在有史以来创建的第一个快照。因此,从创建后的第一个状态更改开始,该闭包将成为陈旧的闭包,也就是“不同步”。
而且由于上面提到的闭包链,整个链都停滞了,从调用点useEffect
回调开始。因此更新的 info
值不会通过 setState({ ...info })
调用反映...
除非您从一开始就避免 capturing/snapshoting 行为!魔术代码就是这样做的。它避免通过闭包捕获来引用 info
,而是从
setState(info => ...)
虽然闭合链仍然是 stale
,但它没有造成真正的伤害,因为它没有引用任何外部值。 setState
将确保 info
参数始终设置为最新状态值。