reactjs - 无法在 useEffect 中对未安装的组件执行 React 状态更新
问题描述
我有一个 REACT NATIVE 应用程序,在一个组件中,我用 AXIOS 调用一个 API 来从数据库中获取行。
我有loadData函数,它执行对数据库的调用并在状态中设置一些信息来监视执行并保存结果。我在useEffect中调用这个loadData但是当我改变屏幕时我收到Can't perform a React state update on an unmounted component
这是我的组件:
const HomeScreen = props => {
//I take the id from the state
const Id = useSelector(state => state.auth.Id);
const [data, setData] = useState();
const [loading, setLoading] = useState(false);
const [error, setError] = useState();
//Manage the duration of the http request
const [executionDuration, setExecutionDuration] = useState(0);
const [deleteExecutionCounting, setDeleteExecutionCounting] = useState(0);
const executionDurationRef = useRef(executionDuration);
executionDurationRef.current = executionDuration;
const deleteExecutionCountingRef = useRef(deleteExecutionCounting);
deleteExecutionCountingRef.current = deleteExecutionCounting;
//call the api
//the call to the api has made manually
const loadData = useCallback(() => {
setDeleteExecutionCounting(setInterval((() => {
setExecutionDuration(executionDurationRef.current + 1);
}), 2000));
setError(false);
setLoading(true);
getRowsFromDb(Id).then(function (response) {
if (response.status === 204) {
setData({ rows: [], count: 0 });
}
else {
setData(response.data);
}
})
.catch(function (error) {
setError(true)
})
.then(function () {
// always executed
clearInterval(deleteExecutionCountingRef.current);
setExecutionDuration(0);
setDeleteExecutionCounting(0);
setLoading(false);
});
}, [Id]);
//this is used to refresh the data every time the screen is visible
useEffect(() => {
const unsubscribe = props.navigation.addListener('focus', () => {
// The screen is focused
loadData();
});
// Return the function to unsubscribe from the event so it gets removed on unmount
return unsubscribe;
}, [Id, props.navigation, loadData]);
useEffect(() => {
loadData();
}, [Id, props.navigation, loadData]);
//check Loading state
if (loading)
return (
<View style={styles.screenMessage}>
<ActivityIndicator size='large' />
{executionDurationRef.current > 3 &&
(
<Text>We're taking too long</Text>
)}
{executionDurationRef.current > 6 &&
(<View>
<Text>there is something wrong</Text>
</View>
)}
</View>
)
//check error state
if (error) {
console.log(errorOrders);
return (
<View style={styles.screenMessage}>
<Error onPress={() => { loadData(); }}>Try again</Error>
</View>
)
}
//This is made for the first rendering to avoid to reach the code down when the value should be initialized
if ((!loading && data === undefined)) {
return null;
}
return (
//normal rendering of a component
);
};
const styles = StyleSheet.create({
screenMessage: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: Colors.bodyBackgroundColor
},
bodyContainer: {
flex: 1,
justifyContent: "center",
backgroundColor: Colors.bodyBackgroundColor
},
});
export default HomeScreen;
我该如何解决这个问题?
解决方案
推荐阅读
- python - 如何跨多个工作表对相同的列进行排序?
- python - 在 read_pickle 之后追加
- ruby - Ruby / Redmine:从问题主题和适当的自定义字段编译哈希
- python - AttributeError:“历史”对象没有属性“predict_classes”
- android - org.jsoup.HttpStatusException:获取 URL 的 HTTP 错误。状态=403
- python - 使用 pygame.KEYDOWN 拾取方块
- pyspark - 计算 PySpark 中数组的滚动总和并保存为 dict?
- c# - 异步等待与等待 task.run
- mongodb - mongoldb 无法连接到本地主机套接字异常
- python - Python 日历