英文:
Getting AsyncStorage in useEffect is not setting the state before I call the fetch function
问题
以下是翻译好的部分:
我正在使用这个库:
const [userId, setUserId] = useState('');
import AsyncStorage from '@react-native-async-storage/async-storage';
当我在这里登录时,我设置了 AsyncStorage:
const storeUserId = async (id) => {
try {
await AsyncStorage.setItem(
'userId',
id,
);
} catch (error) {
console.log(error);
}
}
像这样:
storeUserId(userGuid);
navigation.navigate("Home");
然后当我导航到主屏幕时,我在 useEffect 中有这个:
useEffect(() => {
AsyncStorage.getItem('userId').then(value => {
if (value != null) {
setUserId(value.toString());
console.log("u " + value);
getData(0);
}
});
}, []);
控制台日志输出:
u 52ba85d7-5d16-4012-940d-94cddda978b2
这是正确的,但当在这里调用 getData(0); 时:
const getData = async (id) => {
console.log("2 " + userId);
setOnRefresh(true);
fetch('https://soppinga.com/api/Home/GetPolls?id=' + id + "&userId=" + userId, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
})
.then(function(response){
return response.json();
})
.then(function(json){
heartRef2.current = true;
heartRef.current = true;
loadData(json);
setOnRefresh(false);
})
.catch(function(error) {
console.log('发生了一个问题: ' + error.message);
// 添加此处的错误处理
throw error;
});
}
控制台日志输出空的 userId,因此我的 fetch 无法在 userId 为空的情况下完成。
那么,我如何及时获取 userId 并能够及时将其传递给 fetch?
英文:
I'm using this library:
const [userId, setUserId] = useState('');
import AsyncStorage from '@react-native-async-storage/async-storage';
When I Login here, I set the AsyncStorage:
const storeUserId = async (id) => {
try {
await AsyncStorage.setItem(
'userId',
id,
);
} catch (error) {
console.log(error);
}
}
As so:
storeUserId(userGuid);
navigation.navigate("Home");
Then when i navigate to the Home Screen, i have this in useEffect:
useEffect(() => {
AsyncStorage.getItem('userId').then(value => {
if (value != null) {
setUserId(value.toString());
console.log("u " + value);
getData(0);
}
});
}, []);
The console log outputs:
u 52ba85d7-5d16-4012-940d-94cddda978b2
Which is correct, but when getData(0); is called here:
const getData = async (id) => {
console.log("2 " + userId);
setOnRefresh(true);
fetch('https://soppinga.com/api/Home/GetPolls?id=' + id + "&userId=" + userId, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}})
.then(function(response){
return response.json();
})
.then(function(json){
heartRef2.current = true;
heartRef.current = true;
loadData(json); setOnRefresh(false);
})
.catch(function(error) {
console.log('There has been a problem with your fetch operation: ' + error.message);
// ADD THIS THROW error
throw error;
});
}
The console log outputs empty userId, so my fetch cannot complete with the userId as empty.
So how do I get the userId in time and be able to pass it in the fetch in time?
答案1
得分: 1
很高兴看到你解决了你的问题,虽然它适用于你的情况,但你需要小心,这与"争取时间"让第一个效果完成无关,当你设置一个状态时,无法在同一渲染中访问该状态的新数据。拆分效果解决了这个问题,因为第二个效果现在会在userId更改后触发,这是在下一次渲染之后,它将能够在其作用域中访问新状态。
如果你想在设置状态后直接使用状态的值,那么只需使用值本身,而不是像这样使用状态:
useEffect(() => {
AsyncStorage.getItem('userId').then(value => {
if (value != null) {
const newUserId = value.toString()
setUserId(newUserId);
console.log("userId " + newUserId);
getData(newUserId) // 将其传递给 getData 函数
}
});
}, []);
英文:
Nice to see you solved you problem, while it works for your case you need to be careful that it's not about "buying time" for the first effect to finish, when you set a state, the new data of the state cannot be accessed in the same render. splitting the effects solved the issue because the second effect will now fire the next time userId changes which is after the next render and it will have access to the new state in its scope
https://react.dev/reference/react/useEffect
It you want to use the value of the state directly after setting it, then just use the value itself, and not the state like this:
useEffect(() => {
AsyncStorage.getItem('userId').then(value => {
if (value != null) {
const newUserId = value.toString()
setUserId(newUserId);
console.log("userId " + newUserId);
getData(newUserId) // pass it to the getData function
}
});
}, []);
答案2
得分: 0
我必须这样分开使用useEffect
:
useEffect(() => {
AsyncStorage.getItem('userId').then(value => {
if (value != null) {
setUserId(value.toString());
console.log("u " + value);
}
});
}, []);
useEffect(() => {
if(userId.length > 0){
getData(0);
}
}, [userId]);
因此,当调用setUserId
时,包含getData()
的useEffect
将被调用,以确保userId
被设置足够的时间。
英文:
I had to separate the useEffect like this:
useEffect(() => {
AsyncStorage.getItem('userId').then(value => {
if (value != null) {
setUserId(value.toString());
console.log("u " + value);
}
});
}, []);
useEffect(() => {
if(userId.length > 0){
getData(0);
}
}, [userId]);
So when the setUserId is called, the useEffect containing the getData() will be called for enough time for the userId to be set
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论