问题
I am executing useEffect() to update a state with JSON data. However the fetch request sometimes fails, so I want to re-execute the useEffect hook if that happens:
...
import React, {useState, useEffect} from 'react';
import {getJsonData} from './getJsonData';
const myApp = () => {
var ErrorFetchedChecker = false;
const [isLoading,setIsLoading] = useState(true);
const [data,setData] = useState(null);
const updateState = jsonData => {
setIsloading(false);
setData(jsonData);
};
useEffect(() => {
//console.log('EXECUTING');
getJsonData().then(
data => updateState(data),
error => {
Alert.alert('DATA FETCHING ERROR !', 'Refreshing ?...');
ErrorFetchedChecker = !ErrorFetchedChecker;
//console.log('LOG__FROM_CountriesTable: Executed');
},
);
}, [ErrorFetchedChecker]);//Shouldn't the change on this variable
//be enough to re-execute the hook ?
return (
<View>
<Text>{state.data.title}</Text>
<Text>{data.data.completed}</Text>
</View>
);
}
Here's the getJsonData() function just in case:
export async function getJsonData() {
try {
let response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
let responseJson = await response.json();
return responseJson;
} catch (error) {
throw error;
// Also, is this the correct way to handle the error ?
// As the Alert in useEffect goes off either ways.
// If not, advise me on how the error should be handled.
}
}
回答1:
This will work
const myApp = () => {
const [errorFetchedChecker, setErrorFetchedChecker] = useState(false);
const [isLoading,setIsLoading] = useState(true);
const [data,setData] = useState(null);
const updateState = jsonData => {
setIsloading(false);
setData(jsonData);
};
useEffect(() => {
//console.log('EXECUTING');
getJsonData().then(
data => updateState(data),
error => {
Alert.alert('DATA FETCHING ERROR !', 'Refreshing ?...');
setErrorFetchedChecker(c => !c);
//console.log('LOG__FROM_CountriesTable: Executed');
},
);
}, [errorFetchedChecker]);
return (
<View>
<Text>{state.data.title}</Text>
<Text>{data.data.completed}</Text>
</View>
);
}
回答2:
import React, { useState, useRef, useEffect } from "react";
import { Text, View, TextInput } from "react-native";
const App = () => {
var ErrorFetchedChecker = false;
const [isLoading, setIsLoading] = useState(true);
const [data, setData] = useState(null);
const updateState = (jsonData) => {
setIsLoading(false);
setData(jsonData);
};
useEffect(() => {
//console.log('EXECUTING');
getJsonData()
.then((data) => {
console.log("1. Successful, just received the data from our promise");
updateState(data);
console.log("2. We set our data because we received it successfully");
return { alreadySet: true };
})
.catch((e) => {
console.log("1. We failed to gather data in our initial promise");
console.log("2. Attempting to rerun initial promise");
return getJsonData();
})
.then((data) => {
if (data.alreadySet) {
console.log(
"3. Did not attempt to retry because we are already successful"
);
} else {
console.log("3. Our second attempt succeeded");
updateState(data);
console.log("4. Set our data on our second attempt");
}
})
.catch((e) => {
console.log("3. Both attempts have failed");
});
}, []); //Shouldn't the change on this variable
//be enough to re-execute the hook ?
return (
<View>
<Text>{data ? <Text>{data.title}</Text> : null}</Text>
</View>
);
};
export async function getJsonData() {
try {
let response = await fetch("https://jsonplaceholder.typicode.com/todos/1");
let responseJson = await response.json();
return responseJson;
} catch (error) {
throw error;
// Also, is this the correct way to handle the error ?
// As the Alert in useEffect goes off either ways.
// If not, advise me on how the error should be handled.
}
}
export default App;
来源:https://stackoverflow.com/questions/60872890/re-calling-useeffect-after-a-failed-api-fetching-request