在React Amplify中使用AWS Cognito自定义属性作为查询过滤器遇问题
解决方案:从Cognito获取自定义属性并用于Amplify Data查询过滤
问题根源分析
- 初始默认值干扰:你设置的默认值
"999999999"会在异步获取属性完成前显示,导致短暂的错误状态。 - 异步操作未处理错误:
fetchUserAttributes可能返回的属性中没有custom:customer_id,或者调用失败,直接返回undefined。 - useEffect依赖缺失:第一个
useEffect没有依赖数组,会在组件每次渲染时重复执行,可能导致状态混乱。 - 查询未做条件判断:当
companyId为undefined时,依然执行查询,可能引发无效请求。
具体修复步骤
1. 完善用户属性获取函数,添加错误处理与日志
确保能捕获异常,并确认自定义属性是否存在:
const getUserAttributes = async () => { try { const userAttributes = await fetchUserAttributes(); // 打印属性确认是否包含custom:customer_id console.log('用户属性:', userAttributes); const customerId = userAttributes['custom:customer_id']; if (!customerId) { throw new Error('用户属性中未找到custom:customer_id'); } return customerId.toString(); } catch (err) { console.error('获取用户属性失败:', err); return null; } };
2. 调整组件状态与useEffect逻辑
- 移除误导性的默认值,改用
null作为初始状态 - 添加加载状态,避免初始值显示
- 确保获取属性的
useEffect仅执行一次 - 仅当
companyId有效时才执行查询,并清理订阅避免内存泄漏
修改后的组件代码:
import { useEffect, useState } from "react"; import type { Schema } from "../amplify/data/resource"; import { generateClient } from "aws-amplify/data"; import { Authenticator } from '@aws-amplify/ui-react' import '@aws-amplify/ui-react/styles.css' import Container from 'react-bootstrap/Container'; import { fetchUserAttributes } from 'aws-amplify/auth'; import AccountSummary from "./AccountSummary"; import CustomerRecommendations from "./CustomerRecommendations"; const client = generateClient<Schema>(); const getUserAttributes = async () => { try { const userAttributes = await fetchUserAttributes(); console.log('用户属性:', userAttributes); const customerId = userAttributes['custom:customer_id']; if (!customerId) { throw new Error('用户属性中未找到custom:customer_id'); } return customerId.toString(); } catch (err) { console.error('获取用户属性失败:', err); return null; } }; function App() { const [summaries, setSummaries] = useState<Array<Schema["CustomerSummary"]["type"]>>([]); const [recommendations, setRecommendations] = useState<Array<Schema["CustomerRecommendation"]["type"]>>([]); const [companyId, setCompanyId] = useState<string | null>(null); const [isLoading, setIsLoading] = useState(true); // 仅在组件挂载时获取一次用户属性 useEffect(() => { const loadCompanyId = async () => { const customerId = await getUserAttributes(); setCompanyId(customerId); setIsLoading(false); }; loadCompanyId(); }, []); // 查询CustomerSummary,仅当companyId有效时执行 useEffect(() => { if (!companyId) return; const subscription = client.models.CustomerSummary.observeQuery({ filter: { customer_id: { eq: companyId } } }).subscribe({ next: (data) => setSummaries([...data.items]), error: (err) => console.error('获取汇总数据失败:', err) }); // 组件卸载时清理订阅 return () => subscription.unsubscribe(); }, [companyId]); // 查询CustomerRecommendations,仅当companyId有效时执行 useEffect(() => { if (!companyId) return; const subscription = client.models.CustomerRecommendation.observeQuery({ filter: { customer_id: { eq: companyId } } }).subscribe({ next: (data) => setRecommendations([...data.items]), error: (err) => console.error('获取推荐数据失败:', err) }); return () => subscription.unsubscribe(); }, [companyId]); // 加载中状态 if (isLoading) { return <div>加载中...</div>; } // 未获取到有效companyId时显示错误 if (!companyId) { return <div>无法获取客户ID,请检查认证状态。</div>; } return ( <Authenticator> <Container> <AccountSummary summaries={summaries} /> <CustomerRecommendations recommendations={recommendations} /> </Container> </Authenticator> ); } export default App;
额外注意事项
- 确认Cognito用户池已正确配置
custom:customer_id自定义属性,并且在用户注册/更新时已赋值。 - 检查Cognito应用客户端是否有读取自定义属性的权限(在用户池应用客户端设置中,确保
custom:customer_id在允许的属性列表里)。
内容的提问来源于stack exchange,提问作者P Hopkins
相关产品推荐
相关产品推荐

