React Hooks结合三元运算符调用的代码实现及技术问询
React Hooks结合三元运算符的实现分析与优化建议
代码实现逻辑解析
这段代码的核心意图很明确:
- 通过自定义
useFetch钩子分别请求全量用户列表(allUsers,仅依赖id)和带权限过滤的用户列表(usersWithoutAccess,依赖id和queryParams) - 同时请求当前用户的权限数据
permission(依赖id) - 最终根据
permission.value的布尔值,决定使用全量用户还是过滤后的用户列表
现有写法的问题
- 不必要的重复请求:不管
permission.value最终是true还是false,两个useFetch(fetchUsersApi)都会被执行,导致两次接口调用,浪费网络资源和服务器算力。 - 初始状态逻辑模糊:当
permission处于加载状态时(比如data还未返回),permission.value可能为undefined,此时三元表达式会默认取usersWithoutAccess,这可能不符合业务预期。 - 依赖冗余:两个用户列表请求都依赖
id,但第二个多了queryParams,如果queryParams变化,会触发重复请求,但此时可能不需要。
React Hooks结合三元运算符的正确姿势
React的Hooks规则明确要求:Hooks必须在组件的顶层调用,不能放在条件语句、循环或嵌套函数中。所以以下写法是绝对禁止的:
// ❌ 违反Hooks规则:条件调用Hooks const users = permission.value ? useFetch(fetchUsersApi, [id]) : useFetch(fetchUsersApi, [id, queryParams]);
优化方案1:根据权限动态调整请求依赖(推荐)
如果fetchUsersApi支持通过参数传递权限过滤条件,可以合并成一次请求,彻底避免重复调用:
const { data: permission } = useFetch(fetchPermissionApi, [id]); // 根据权限动态生成请求依赖和参数 const fetchDeps = permission.value ? [id] : [id, queryParams]; const users = useFetch(fetchUsersApi, fetchDeps);
这样只会发起一次用户列表请求,且依赖会根据权限变化自动更新。
优化方案2:用useMemo延迟选择结果(适合无法合并请求的场景)
如果必须分开请求两个列表,可以用useMemo配合加载状态,避免在权限未就绪时返回错误结果:
const allUsers = useFetch(fetchUsersApi, [id]); const usersWithoutAccess = useFetch(fetchUsersApi, [id, queryParams]); const { data: permission, loading: permissionLoading } = useFetch(fetchPermissionApi, [id]); // 权限加载完成后再选择结果,加载中可以返回统一的loading状态 const users = useMemo(() => { if (permissionLoading) return { loading: true }; return permission.value ? allUsers : usersWithoutAccess; }, [permissionLoading, permission, allUsers, usersWithoutAccess]);
这种方式虽然还是会发起两次请求,但能避免初始状态的逻辑错误。
优化方案3:条件触发请求(性能最优)
借助useEffect和useState,只有当权限确定后,才发起对应的用户列表请求:
const { data: permission, loading: permissionLoading } = useFetch(fetchPermissionApi, [id]); const [users, setUsers] = useState({ loading: true }); useEffect(() => { if (permissionLoading) return; // 根据权限选择对应的请求逻辑 const fetchAction = permission.value ? () => fetchUsersApi(id) : () => fetchUsersApi(id, queryParams); fetchAction().then(res => setUsers({ loading: false, data: res })) .catch(err => setUsers({ loading: false, error: err })); }, [permissionLoading, permission, id, queryParams]);
这种方式完全避免了不必要的请求,只在权限确定后发起一次请求,性能最优。
内容的提问来源于stack exchange,提问作者Mesha
相关产品推荐
相关产品推荐

