我在 React Native 应用程序中有一个屏幕,我在其中使用
useQuery
获取一些数据,使用 setState
将此数据保存在对象状态中,然后更新子组件内的状态值。获取数据后我陷入状态初始化。使用现已弃用的 onSuccess
钩子可能会容易得多,但我想知道是否有更好的替代方案。
我正在使用
React 18
、React Native 0.72
和 React Query v5
。
我尝试了以下方法:
select
属性:const {refetch, data, isLoading, error} = useQuery({
queryKey: ['leadPreferences'],
queryFn: async () => getLeadPreferences(setLoggedIn),
select: (res) => {
if (res != null) {
const leadPreferencesData = res.body;
console.log('running this: ', i++);
return updateLeadPreferences({
destinations: [],
whatsAppContact: leadPreferencesData.whatsapp_contact,
whatsAppCommStatus: leadPreferencesData.whatsapp_enabled,
leadEmail: leadPreferencesData.alert_email_ids,
emailAlertStatus: leadPreferencesData.email_alert_enabled,
emailAlertTimes: [],
leadTypes: leadPreferencesData.lead_types,
packageTypes: leadPreferencesData.package_types,
defaultHomePage: leadPreferencesData.landing_page,
});
}
},
});
这会引发
data is undefined
错误。
2. useQuery 调用之前和之后的
useEffect
方法:
useEffect(() => {
if (data && data != undefined) {
const leadPreferencesData = data.body;
console.log('running this: ', i++);
updateLeadPreferences({
destinations: [],
whatsAppContact: leadPreferencesData.whatsapp_contact,
whatsAppCommStatus: leadPreferencesData.whatsapp_enabled,
leadEmail: leadPreferencesData.alert_email_ids,
emailAlertStatus: leadPreferencesData.email_alert_enabled,
emailAlertTimes: [],
leadTypes: leadPreferencesData.lead_types,
packageTypes: leadPreferencesData.package_types,
defaultHomePage: leadPreferencesData.landing_page,
});
}
},);
应该发生什么:
每当
data
的值发生变化时,状态都必须更新。
问题:
抛出“无法读取未定义的属性” -> 如果在 useQuery 挂钩之前调用 useEffect
“比之前的渲染期间渲染了更多的钩子” -> 如果在 useQuery 之后调用 useEffect,并使用 data
作为依赖数组。
updateLeadPreferences
。
在调试器抛出“太多重新渲染”错误之前,这会导致大约 51 次渲染。你能尝试一次然后告诉我吗? (如下)
使用 useQuery 获取数据,而无需尝试直接在选择函数中设置状态。选择选项应该纯粹用于选择或转换要在组件中使用的数据,而不是用于更新状态等副作用。利用 useEffect 来观察 useQuery 返回的数据的变化,然后相应地更新组件的状态。
//small example in line with your code
import React, { useState, useEffect } from 'react';
import { useQuery } from 'react-query';
const initialLeadPreferencesState = {
destinations: [],
whatsAppContact: '',
whatsAppCommStatus: false,
leadEmail: '',
emailAlertStatus: false,
emailAlertTimes: [],
leadTypes: [],
packageTypes: [],
defaultHomePage: '',
};
const YourComponent = () => {
const [leadPreferences, setLeadPreferences] = useState(initialLeadPreferencesState);
const { data, isLoading, error } = useQuery('leadPreferences', async () => {
const response = await getLeadPreferences();
return response.body;
});
useEffect(() => {
if (data) {
const leadPreferencesData = data;
setLeadPreferences({
...leadPreferences,
whatsAppContact: leadPreferencesData.whatsapp_contact,
whatsAppCommStatus: leadPreferencesData.whatsapp_enabled,
leadEmail: leadPreferencesData.alert_email_ids,
emailAlertStatus: leadPreferencesData.email_alert_enabled,
leadTypes: leadPreferencesData.lead_types,
packageTypes: leadPreferencesData.package_types,
defaultHomePage: leadPreferencesData.landing_page,
});
}
}, [data]); // Dependency array ensures this effect runs only when `data` changes
if (isLoading) return <div>Loading...</div>;
if (error) return <div>An error occurred</div>;
return (
<div>
{/* Render your UI here using `leadPreferences` state */}
</div>
);
};