React - 使用钩子重构逻辑
React - Refactoring logic with hooks
简介
我有一个向我的服务器查询的屏幕:
通过用户名获取用户(当用户在搜索输入中输入内容时)
获取高级用户(挂载屏幕时 + 下拉刷新)
获取年轻用户(挂载屏幕时 + 拉动刷新)
我正在考虑将其移到钩子上。
这是我当前的代码:
function MyScreen() {
// Fetch by username
const [isSearching, setIsSearching] = useState([]);
const [searchedUsers, setSearchedUsers] = useState([]);
// Premium
const [isLoading, setIsLoading] = useState(true); <--- NOTE THIS
const [premiumUsers, setPremiumUsers] = useState([]);
// Young users
const [youngUsers, setYoungUsers] = useState([]);
/*
FIRST METHOD
*/
const searchUsersByUsername = async (limit = 20) => {
setIsSearching(true);
try {
const result = await api.users.searchUsersByUsername(username, limit);
setSearchedUsers(result);
} catch(err) {
console.log(err);
}
setIsSearching(false);
}
/*
SECOND METHOD
*/
const getPremiumUsers = async (limit = 10) => {
// Note: No loading here
try {
const result = await api.users.getPremiumUsers(limit);
setPremiumUsers(result);
} catch(err) {
console.log(err);
}
}
/*
THIRD METHOD
*/
const getYoungUsers = async (limit = 10) => {
// Note: No loading here
try {
const result = await api.users.getYoungUsers(limit);
setYoungUsersUsers(result);
} catch(err) {
console.log(err);
}
}
// Effects and rendering...
useEffect(() => {
(async () => {
const promises = [getPremiumUsers(), getYoungUsers()];
await Promise.all(promises).catch((err) => {
console.log(err))
});
setIsLoading(false); // <---- NOTE THIS
})();
}, []);
}
问题
我无法使用典型的 useQuery 挂钩,因为我正在使用 Firestore 可调用函数。因此,发出请求的唯一方法是调用我的 api 方法 (api.users.searchUser...)
正如你在代码中看到的,我有两种加载指示器(两种状态):
isSearching(用于按用户名搜索功能)
isLoading(用于并行获取高级用户和年轻用户)
如何为这个逻辑实现可重用的钩子?
我的意思是,我需要抽象所有这些东西,以便能够:
在其他页面按用户名搜索用户
搜索高级用户(不并行获取年轻用户)
搜索年轻用户(不并行获取高级用户)
同时,获取三个查询的加载状态。
注意:在我当前的屏幕中,正如我之前所说,我正在为年轻和高级用户使用“setIsLoading”并行 抓取,但也许(为了更灵活) 在其他屏幕中,我将独立需要每个逻辑的加载状态。
有什么帮助或想法吗?
您可以通过每个获取方法使用 React.useEffect
和 React.useCallback
。
另外,单独保存加载状态。
看看这个:
import { useEffect, useCallback } from 'react';
const defaultParams = {
fetchPremiumUsersOnMount: false,
fetchYoungUsersOnMount: false,
searchOnMount: false,
username: '',
limit: 20,
}
function useUsersApi(params = defaultParams) {
const [isSearching, setIsSearching] = useState(false);
const [searchedUsers, setSearchedUsers] = useState([]);
const [premiumUsers, setPremiumUsers] = useState([]);
const [premiumLoading, setPremiumLoading] = useState(false);
const [youngUsers, setYoungUsers] = useState([]);
const [youngLoading, setYoungLoading] = useState(false);
const fetchPremiumUsers = useCallback(async () => {
try {
setPremiumLoading(true);
const result = api.users.getPremiumUsers(params.limit);
setPremiumUsers(result);
} catch (err) {
console.log(err)
} finally {
setPremiumLoading(false);
}
}, [params.limit]);
const fetchYoungUsers = useCallback(async () => {
/* similar logic to `fetchPremiumUsers` */
}, [params.limit, params.]);
const fetchSearchUsers = useCallback(async (username) => {
/* fetch logic here */
}, [params.limit]);
useEffect(() => {
if(params.fetchPremiumUsersOnMount) {
fetchPremiumUsers();
}
}, [params.fetchPremiumUsersOnMount, params.limit]);
useEffect(() => {
if(params.fetchYoungUsersOnMount) {
fetchYoungUsers();
}
}, [params.fetchYoungUsersOnMount, params.limit]);
useEffect(() => {
if(params.fetchSearchUsers) {
fetchSearchUser(params.username);
}
}, [params.searchOnMount, params.limit, params.username]);
return {
isSearching,
searchedUsers,
isLoading: premiumLoading || youngLoading,
premiumUsers,
premiumUsersLoading: premiumLoading,
refreshPremiumUsers: fetchPremiumUsers,
youngUsers,
youngUsersLoading: youngLoading,
refreshYoungUsers: fetchYoungUsers,
}
}
简介
我有一个向我的服务器查询的屏幕:
通过用户名获取用户(当用户在搜索输入中输入内容时)
获取高级用户(挂载屏幕时 + 下拉刷新)
获取年轻用户(挂载屏幕时 + 拉动刷新)
我正在考虑将其移到钩子上。
这是我当前的代码:
function MyScreen() {
// Fetch by username
const [isSearching, setIsSearching] = useState([]);
const [searchedUsers, setSearchedUsers] = useState([]);
// Premium
const [isLoading, setIsLoading] = useState(true); <--- NOTE THIS
const [premiumUsers, setPremiumUsers] = useState([]);
// Young users
const [youngUsers, setYoungUsers] = useState([]);
/*
FIRST METHOD
*/
const searchUsersByUsername = async (limit = 20) => {
setIsSearching(true);
try {
const result = await api.users.searchUsersByUsername(username, limit);
setSearchedUsers(result);
} catch(err) {
console.log(err);
}
setIsSearching(false);
}
/*
SECOND METHOD
*/
const getPremiumUsers = async (limit = 10) => {
// Note: No loading here
try {
const result = await api.users.getPremiumUsers(limit);
setPremiumUsers(result);
} catch(err) {
console.log(err);
}
}
/*
THIRD METHOD
*/
const getYoungUsers = async (limit = 10) => {
// Note: No loading here
try {
const result = await api.users.getYoungUsers(limit);
setYoungUsersUsers(result);
} catch(err) {
console.log(err);
}
}
// Effects and rendering...
useEffect(() => {
(async () => {
const promises = [getPremiumUsers(), getYoungUsers()];
await Promise.all(promises).catch((err) => {
console.log(err))
});
setIsLoading(false); // <---- NOTE THIS
})();
}, []);
}
问题
我无法使用典型的 useQuery 挂钩,因为我正在使用 Firestore 可调用函数。因此,发出请求的唯一方法是调用我的 api 方法 (api.users.searchUser...)
正如你在代码中看到的,我有两种加载指示器(两种状态):
isSearching(用于按用户名搜索功能)
isLoading(用于并行获取高级用户和年轻用户)
如何为这个逻辑实现可重用的钩子?
我的意思是,我需要抽象所有这些东西,以便能够:
在其他页面按用户名搜索用户
搜索高级用户(不并行获取年轻用户)
搜索年轻用户(不并行获取高级用户)
同时,获取三个查询的加载状态。
注意:在我当前的屏幕中,正如我之前所说,我正在为年轻和高级用户使用“setIsLoading”并行 抓取,但也许(为了更灵活) 在其他屏幕中,我将独立需要每个逻辑的加载状态。
有什么帮助或想法吗?
您可以通过每个获取方法使用 React.useEffect
和 React.useCallback
。
另外,单独保存加载状态。
看看这个:
import { useEffect, useCallback } from 'react';
const defaultParams = {
fetchPremiumUsersOnMount: false,
fetchYoungUsersOnMount: false,
searchOnMount: false,
username: '',
limit: 20,
}
function useUsersApi(params = defaultParams) {
const [isSearching, setIsSearching] = useState(false);
const [searchedUsers, setSearchedUsers] = useState([]);
const [premiumUsers, setPremiumUsers] = useState([]);
const [premiumLoading, setPremiumLoading] = useState(false);
const [youngUsers, setYoungUsers] = useState([]);
const [youngLoading, setYoungLoading] = useState(false);
const fetchPremiumUsers = useCallback(async () => {
try {
setPremiumLoading(true);
const result = api.users.getPremiumUsers(params.limit);
setPremiumUsers(result);
} catch (err) {
console.log(err)
} finally {
setPremiumLoading(false);
}
}, [params.limit]);
const fetchYoungUsers = useCallback(async () => {
/* similar logic to `fetchPremiumUsers` */
}, [params.limit, params.]);
const fetchSearchUsers = useCallback(async (username) => {
/* fetch logic here */
}, [params.limit]);
useEffect(() => {
if(params.fetchPremiumUsersOnMount) {
fetchPremiumUsers();
}
}, [params.fetchPremiumUsersOnMount, params.limit]);
useEffect(() => {
if(params.fetchYoungUsersOnMount) {
fetchYoungUsers();
}
}, [params.fetchYoungUsersOnMount, params.limit]);
useEffect(() => {
if(params.fetchSearchUsers) {
fetchSearchUser(params.username);
}
}, [params.searchOnMount, params.limit, params.username]);
return {
isSearching,
searchedUsers,
isLoading: premiumLoading || youngLoading,
premiumUsers,
premiumUsersLoading: premiumLoading,
refreshPremiumUsers: fetchPremiumUsers,
youngUsers,
youngUsersLoading: youngLoading,
refreshYoungUsers: fetchYoungUsers,
}
}