使用SWR拉取接口数据传入Antd Cascader后点击不展示子项如何解决
Ant Design Cascader 级联选择加载子级无响应问题修复
存在的问题
- 问题1:传参时临时生成options对象,丢失状态
你直接在Cascader的options属性中做map转换,每次渲染都会生成全新的对象,你在loadData中给目标选项添加的loading、children属性都存在state的原对象上,传给组件的新对象根本没有携带这些属性,导致组件感知不到加载完成,也拿不到子级数据。 - 问题2:options state没有同步SWR的异步更新
SWR请求是异步的,组件首次渲染时data大概率还未返回,你仅在useState初始化时赋值一次,后续SWR请求完成返回数据后,options state不会自动更新,导致状态不一致。 - 问题3:loadData存在闭包陷阱
loadData函数里的options是函数创建时的闭包值,setOptions([...options])拿到的永远是函数初始化时的旧值,会导致状态更新丢失。
修复后的代码
const { dataCategories: { data }} = useCategories(); const [options, setOptions] = useState([]); // 同步SWR返回的分类数据到state,提前添加isLeaf属性 useEffect(() => { if (data) { setOptions(data.map(item => ({ ...item, isLeaf: !item.has_children }))) } }, [data]) const loadData = async selectedOptions => { const targetOption = selectedOptions[selectedOptions.length - 1]; // 函数式更新保证拿到最新state,先修改loading状态 setOptions(prev => { return prev.map(item => { if (item.cate_id === targetOption.cate_id) { return { ...item, loading: true } } return item }) }) setTimeout(() => { // 加载完成后更新子级和loading状态 setOptions(prev => { return prev.map(item => { if (item.cate_id === targetOption.cate_id) { return { ...item, loading: false, // 子项也提前添加isLeaf属性 children: [ { cate_name: 'iPhone', cate_id: 1, has_children: false, isLeaf: true }, { cate_name: 'Macbook', cate_id: 2, has_children: false, isLeaf: true } ] } } return item }) }) }, 2000); }; return ( <Cascader fieldNames={{ label: 'cate_name', value: 'cate_id' }} // 直接传state里处理好的options,不要临时做map转换 options={options} loadData={loadData} changeOnSelect placeholder="Please select your category" /> )
内容的提问来源于stack exchange,提问作者Anna
相关产品推荐
相关产品推荐

