Вопрос или проблема
У меня есть асинхронная функция, которая извлекает объект из базы данных (Referral
). В дополнение к основному запросу, различные части приложения также извлекают вспомогательные Referral
с помощью точно такой же функции и ее логики.
Асинхронная функция не может ничего вернуть, поэтому ее не можно использовать как универсальное возвращаемое значение. Вместо этого нам нужно установить переменную состояния с результатами из нее.
Если я сделаю
const [mainReferral, setMainReferral] = useState<Referral|null>(null);
// Извлечение основного реферала
const fetchReferral = async (referralId:string) => {
const response = await get<any>("/referral/" + referralId);
// Много логики ниже, например
response['specialDerivedField1'] = ...;
response['specialDerivedField2'] = ...;
//...
setMainReferral(response);
}
Это обрабатывает только единственный случай основного реферала. У меня также может быть
const [auxReferral1, setAuxReferral1] = useState<Referral|null>(null);
const [auxReferral2, setAuxReferral2] = useState<Referral|null>(null);
//...
Мне действительно нужно добавлять разные параметры в эту функцию, чтобы решить, что установить с помощью if-else
? Это не кажется мне очень надежным.
const fetchReferral = async (referralId:string, case1:boolean, case2:boolean) => {
//...
if (case1)
setAuxReferral1(response);
else if (case2) {
setAuxReferral2(response);
else {
setMainReferral(response);
}
}
Есть ли другие лучшие практики для этого? Или, возможно, передавать строку для имени переменной состояния и затем находить установщик по имени (не уверен, поддерживает ли это React)?
Мне также хотелось бы изолировать эту утилиту в отдельном файле утилиты, который не работает с состоянием, но как асинхронную функцию это будет невозможно, я предполагаю?
Асинхронная функция не может ничего вернуть
Тот, кто вам это сказал, ввел вас в заблуждение. Либо вы могли неправильно понять то, что было сказано.
Ваша async
функция действительно может возвращать результат:
const fetchReferral = async (referralId:string) => {
// существующий код, затем...
return response;
}
И любой компонент может обновить состояние с этим результатом:
// используя await:
const referral = await fetchReferral(someValue);
setMainReferral(referral);
// или используя .then():
fetchReferral(someValue).then(setMainReferral);
В качестве альтернативы, если вы предпочитаете инкапсулировать обработку Promise
в самой функции, вы можете передать установщики состояния как обратный вызов. Например:
const fetchReferral = async (referralId:string, callback:(x:any)=>{}) => {
// существующий код, затем...
callback(response);
}
И любой компонент просто передаст функцию как обратный вызов:
fetchReferral(someValue, setAuxReferral1);
Другим вариантом может быть обертка операции и состояния в пользовательский хуку. Например:
const useReferral = function () => {
const [referral, setReferral] = useState();
const fetchReferral = async (referralId:string) => {
// существующий код, затем...
setReferral(response);
}
return {
referral, fetchReferral
};
};
И любой компонент просто будет использовать этот хук:
const { referral, fetchReferral } = useReferral();
// где-то в логике вашего компонента:
fetchReferral(someValue);
// и используйте "referral" как значение состояния
Ответ или решение
Эффективное использование асинхронной функции для установки состояний в React
Вопрос, с которым вы столкнулись, касается оптимизации кода в React-приложении при работе с асинхронными функциями. Вам нужно извлекать данные из базы данных и обновлять множественные состояния без усложнения логики. Давайте разберем несколько подходов к решению проблемы.
1. Понимание возвращаемых значений асинхронных функций
Похоже, существует недопонимание относительно возвращаемых значений асинхронных функций. Асинхронные функции в JavaScript действительно могут возвращать значения. Например, вы можете вернуть данные, которые затем использует компонент React для обновления состояния:
const fetchReferral = async (referralId: string) => {
const response = await get<any>(`/referral/${referralId}`);
// Дополнительная логика...
return response;
};
// Использование await для установки состояния
const mainReferral = await fetchReferral(someValue);
setMainReferral(mainReferral);
// Или с использованием .then()
fetchReferral(someValue).then(setMainReferral);
Такой подход делает вашу функцию более чистой и позволяет избежать использования сложной логики и дополнительных параметров.
2. Передача колбеков
Другим эффективным вариантом может быть передача функции-колбека в вашу асинхронную функцию. Это позволит вам непосредственно управлять состоянием из компонента, не нагружая саму функцию:
const fetchReferral = async (referralId: string, callback: (x: any) => void) => {
const response = await get<any>(`/referral/${referralId}`);
// Дополнительная логика...
callback(response);
};
// В компоненте
fetchReferral(someValue, setAuxReferral1);
Этот подход делает код более гибким и легким для тестирования, так как вы четко разделяете логику получения данных и логику управления состоянием.
3. Создание пользовательского хука
Однако наиболее элегантным решением может стать создание пользовательского хука, который будет инкапсулировать как логику получения данных, так и состояние. Это позволит вам повысить повторное использование кода и минимизировать избыточность:
const useReferral = () => {
const [referral, setReferral] = useState<Referral | null>(null);
const fetchReferral = async (referralId: string) => {
const response = await get<any>(`/referral/${referralId}`);
// Дополнительная логика...
setReferral(response);
};
return { referral, fetchReferral };
};
// Использование в компоненте
const { referral, fetchReferral } = useReferral();
fetchReferral(someValue);
С помощью пользовательского хука вы получите чистый и понятный API для работы с рефералами, что значительно упростит вашу логику и сократит количество повторяющегося кода.
Заключение
Представленные выше методы помогут эффективно управлять асинхронными операциями и состоянием в вашей React-приложении. Выберите наиболее подходящий для вашего случая вариант, будь то возвращение значений из асинхронной функции, передача колбеков или использование пользовательских хуков. Это не только улучшит читаемость и поддержку вашего кода, но и повысит его производительность.