import React, { useState, useCallback, useEffect } from 'react'; import CustomTrigger from './CustomTrigger'; import { Button, Typography, Toast, Cascader } from '../../index'; const { Text } = Typography; export default { title: 'Cascader', parameters: { chromatic: { disableSnapshot: true }, }, } export { CustomTrigger }; const treeData1 = [ { label: 'Node1', value: '0-0', children: [ { label: 'Child Node1', value: '0-0-1', disabled: true, }, { label: 'Child Node2', value: '0-0-2', }, ], }, { label: 'Node2', value: '0-1', }, ]; const treeData2 = [ { label: '亚洲', value: 'yazhou', children: [ { label: '中国', value: 'zhongguo', children: [ { label: '北京', value: 'beijing', }, { label: '上海', value: 'shanghai', }, ], }, { label: '日本', value: 'riben', disabled: true, children: [ { label: '大阪', value: 'daban', }, ], }, ], }, { label: '北美洲', value: 'beimeizhou', children: [ { label: '美国', value: 'meiguo', }, { label: '加拿大', value: 'jianada', }, ], }, ]; const treeData3 = [ { label: '亚洲', value: 'yazhou', children: [ { label: '中国', value: 'zhongguo', children: [ { label: '北京', value: 'beijing', }, { label: '上海', value: 'shanghai', }, ], }, { label: '日本', value: 'riben', children: [ { label: '大阪', value: 'daban', }, ], }, ], }, ]; const treeData4 = [ { label: '浙江省', value: 'zhejiang', children: [ { label: '杭州市', value: 'hangzhou', children: [ { label: '西湖区', value: 'xihu', }, { label: '萧山区', value: 'xiaoshan', }, { label: '临安区', value: 'linan', }, ], }, { label: '宁波市', value: 'ningbo', children: [ { label: '海曙区', value: 'haishu', }, { label: '江北区', value: 'jiangbei', }, ], }, ], }, ]; const treeOrder = [ { label: '-1', value: '0-0', key: '-1', children: [ { label: 'Child Node1', value: '0-0-1', key: '0-0-1', }, { label: 'Child Node2', value: '0-0-2', key: '0-0-2', }, ], }, { label: '1', value: '0-1', key: '1', }, ]; const longTreeData = [ { label: 'udghajsasndanm,', value: 'A', children: [ { label: 'Bsasfads', value: 'B', children: [ { label: 'C', value: 'C', children: [ { label: 'D', value: 'D', children: [ { label: 'E', value: 'E', children: [ { label: 'F', value: 'F', } ] } ] } ] } ], } ] } ]; const treedataWithNodeLabel = [ { label: '浙江省', value: 'zhejiang', children: [ { label: '杭州市', value: 'hangzhou', children: [ { label: '西湖市区', value: 'xihu', }, { label: '萧山区', value: 'xiaoshan', }, { label: '临安区', value: 'linan', }, ], }, { label: 宁波市, value: 'ningbo', children: [ { label: '海曙区', value: 'haishu', }, { label: '江北区', value: 'jiangbei', } ] }, ], } ]; export const issue703 = () => { const initialData = [ { label: 'Node1', value: '0-0', }, { label: 'Node2', value: '0-1', }, { label: 'Node3', value: '0-2', isLeaf: true }, ]; const [data, setData] = useState(initialData); const updateTreeData = (list, value, children) => { return list.map(node => { if (node.value === value) { return { ...node, children }; } if (node.children) { return { ...node, children: updateTreeData(node.children, value, children) }; } return node; }); }; const onLoadData = selectedOpt => { const targetOpt = selectedOpt[selectedOpt.length - 1]; const { label, value } = targetOpt; return new Promise(resolve => { if (targetOpt.children) { resolve(); return; } setTimeout(() => { setData(origin => updateTreeData(origin, value, [ { label: `${label}-1`, value: `${label}-1`, isLeaf: selectedOpt.length > 1 }, { label: `${label}-2`, value: `${label}-2`, isLeaf: selectedOpt.length > 1 }, ]), ); resolve(); }, 1000); }); }; const [v,setV]=useState([['0-0'], ['0-1', 'Node2-2']]); useEffect(()=>{ console.log('data change'); setTimeout(()=>setV([['0-0'], ['0-1', 'Node2-2', 'Node2-2-2']]),0); },[data]) return ( <>
treeData和value动态更新,value中的值在treeData中存在则能够正确显示
console.log(a)} value={v} style={{ width: 300 }} treeData={data} loadData={onLoadData} placeholder="Please select" />
非受控,动态更新treeData
console.log(a)} style={{ width: 300 }} treeData={data} loadData={onLoadData} placeholder="Please select" /> ); }; export const _Cascader = () => { return (






); }; export const ChangeOnSelect = () => { return (
); }; export const Searchable = () => { return (




console.log(e)} />

fix-1449,当 label 为 ReactNode 时,搜索显示结果[object object]


filterTreeNode=false,且 label 为 ReactNode 时,配合displayRender使用,使得回显到input的内容符合预期
list.map((v, i) => { return list.length - 1 === i ? ( {v} ) : ( {v} / ); }) } defaultValue={['zhejiang', 'ningbo', 'jiangbei']} />

v2.5 起,filterTreeNode=false,且 label 为 ReactNode 时,无配合displayRender 使用,回显到input的内容也是符合预期
); }; Searchable.parameters = { chromatic: { disableSnapshot: false }, } export const filterTreeNodeAndDisplayRender = () => { return ( <>
filterTreeNode=true,配合displayRender 使用,回显到input的内容也是符合预期
{ console.log('item', item); return
{'已选择:' + item.join(' -> ')}
;}} /> ); }; export const Disabled = () => { return (




); }; Disabled.parameters = { chromatic: { disableSnapshot: false }, } export const DisabledOption = () => { return (
common disabled option


single selection + defaultValue is disabled option + changeOnSelect


single selection + defaultValue is disabled option + changeOnSelect + filterTreeNode


multiple selection + defaultValue is disabled option


multiple selection + filterTreeNode + defaultValue is disabled option
); }; export const CustomSearch = () => { return (
); }; export const CustomDisplayProp = () => { return (
); }; export const DefaultValue = () => { return (








); }; export const DefaultValueNotExist = () => { return ( <>

); }; class ControlledDemo extends React.Component { constructor() { super(); this.state = { value: [], }; } onChange(value) { this.setState({ value }); } render() { const treeData = [ { label: '浙江省', value: 'zhejiang', children: [ { label: '杭州市', value: 'hangzhou', children: [ { label: '西湖区', value: 'xihu', }, { label: '萧山区', value: 'xiaoshan', }, { label: '临安区', value: 'linan', }, ], }, { label: '宁波市', value: 'ningbo', children: [ { label: '海曙区', value: 'haishu', }, { label: '江北区', value: 'jiangbei', }, ], }, ], }, ]; return ( this.onChange(e)} /> ); } } export const ControlledComponent = () => ; export const CascaderOrderTest = () => { return (
); }; export const OnFocusAndOnBlur = () => { return (
console.log('focus', e, val)} onBlur={(val, e) => console.log('blur', e, val)} />
); }; export const ShowClear = () => { return (




有用户反馈,超长列表点击 showClear 后,dropdown错位。1.30.0-beta.1 fixed

); }; const LoadDataDemo = () => { const initialData = [ { label: 'Node1', value: '0-0', }, { label: 'Node2', value: '0-1', }, { label: 'Node3', value: '0-2', isLeaf: true, }, ]; const [data, setData] = useState(initialData); const updateTreeData = (list, value, children) => { return list.map(node => { if (node.value === value) { return { ...node, children }; } if (node.children) { return { ...node, children: updateTreeData(node.children, value, children) }; } return node; }); }; const onLoadData = selectedOpt => { const targetOpt = selectedOpt[selectedOpt.length - 1]; const { label, value } = targetOpt; return new Promise(resolve => { if (targetOpt.children) { resolve(); return; } setTimeout(() => { setData(origin => updateTreeData(origin, value, [ { label: `${label} - 1`, value: `${label}-1`, isLeaf: selectedOpt.length > 1, }, { label: `${label} - 2`, value: `${label}-2`, isLeaf: selectedOpt.length > 1, }, ]) ); resolve(); }, 1000); }); }; return ( ); }; const LoadDataWithReset = () => { const initialData = [ { label: 'Node1', value: '0-0', }, { label: 'Node2', value: '0-1', }, { label: 'Node3', value: '0-2', isLeaf: true, }, ]; const [data, setData] = useState(initialData); const [value, setValue] = useState([]); const updateTreeData = (list, value, children) => { return list.map(node => { if (node.value === value) { return { ...node, children }; } if (node.children) { return { ...node, children: updateTreeData(node.children, value, children) }; } return node; }); }; const onLoadData = selectedOpt => { const targetOpt = selectedOpt[selectedOpt.length - 1]; const { label, value } = targetOpt; return new Promise(resolve => { if (targetOpt.children) { resolve(); return; } setTimeout(() => { setData(origin => updateTreeData(origin, value, [ { label: `${label} - 1`, value: `${label}-1`, isLeaf: selectedOpt.length > 1, }, { label: `${label} - 2`, value: `${label}-2`, isLeaf: selectedOpt.length > 1, }, ]) ); resolve(); }, 1000); }); }; return ( <> ); }; export const LoadData = () => ( <>

fix:1448,重置失效
); export const DynamicPlaceholder = () => { const [isSelect, setSelect] = useState(false); return ( <> ); }; export const FixDedupOnSelect = () => { return (
console.log(v)} /> console.log(v)} dedupOnSelect={false} />
); }; const slotStyle = { height: '36px', display: 'flex', padding: '0 32px', alignItems: 'center', cursor: 'pointer', borderRadius: '0 0 6px 6px', }; export const CascaderWithSlot = () => { return (
选择地区} bottomSlot={
找不大相关选项? 去新建
} />
); }; export const CascaderWithMaxTagCountShowRestTagsPopoverRestTagsPopoverProps = () => { return (
); }; CascaderWithMaxTagCountShowRestTagsPopoverRestTagsPopoverProps.story = { name: 'Cascader with maxTagCount/showRestTagsPopover/restTagsPopoverProps', }; CascaderWithMaxTagCountShowRestTagsPopoverRestTagsPopoverProps.parameters = { chromatic: { disableSnapshot: false }, } export const CascaderWithShowNext = () => { return (
); }; export const CascaderWithMaxOnExceed = () => { return (
普通情况
{ Toast.warning('exceed max'); console.log(v); }} defaultValue={['zhejiang', 'ningbo', 'haishu']} />

defaultValue的数量超过max,则只允许减少到合法,不允许再增加
{ Toast.warning('exceed max'); console.log(v); }} defaultValue={[ ['zhejiang', 'ningbo', 'haishu'], ['zhejiang', 'hangzhou', 'xihu'], ]} />

autoMergeValue=false时的情况
{ Toast.warning('exceed max'); console.log(v); }} defaultValue={[ ['zhejiang', 'ningbo', 'haishu'], ['zhejiang', 'hangzhou', 'xihu'], ]} />
); }; CascaderWithMaxOnExceed.story = { name: 'Cascader with max/onExceed', }; CascaderWithMaxOnExceed.parameters = { chromatic: { disableSnapshot: false }, } const ControlledLoadDataWithDefaultValue = () => { const [v, setV] = useState('受控 Value'); const initialData = [ { label: 'Node1', value: '0-0', }, { label: 'Node2', value: '0-1', }, { label: 'Node3', value: '0-2', isLeaf: true, }, ]; const [data, setData] = useState(initialData); const updateTreeData = (list, value, children) => { return list.map(node => { if (node.value === value) { return { ...node, children }; } if (node.children) { return { ...node, children: updateTreeData(node.children, value, children) }; } return node; }); }; const onLoadData = selectedOpt => { const targetOpt = selectedOpt[selectedOpt.length - 1]; const { label, value } = targetOpt; return new Promise(resolve => { if (targetOpt.children) { resolve(); return; } setTimeout(() => { setData(origin => updateTreeData(origin, value, [ { label: `${label} - 1`, value: `${label}-1`, isLeaf: selectedOpt.length > 1, }, { label: `${label} - 2`, value: `${label}-2`, isLeaf: selectedOpt.length > 1, }, ]) ); resolve(); }, 1000); }); }; return ( setV(v)} style={{ width: 300 }} treeData={data} loadData={onLoadData} placeholder="Please select" /> ); }; const LoadDataWithDefaultValue = () => { const initialData = [ { label: 'Node1', value: '0-0', }, { label: 'Node2', value: '0-1', }, { label: 'Node3', value: '0-2', isLeaf: true, }, ]; const [data, setData] = useState(initialData); const updateTreeData = (list, value, children) => { return list.map(node => { if (node.value === value) { return { ...node, children }; } if (node.children) { return { ...node, children: updateTreeData(node.children, value, children) }; } return node; }); }; const onLoadData = selectedOpt => { const targetOpt = selectedOpt[selectedOpt.length - 1]; const { label, value } = targetOpt; return new Promise(resolve => { if (targetOpt.children) { resolve(); return; } setTimeout(() => { setData(origin => updateTreeData(origin, value, [ { label: `${label} - 1`, value: `${label}-1`, isLeaf: selectedOpt.length > 1, }, { label: `${label} - 2`, value: `${label}-2`, isLeaf: selectedOpt.length > 1, }, ]) ); resolve(); }, 1000); }); }; return ( ); }; export const LoadDataWithDefaultValueDemo = () => { return (
fix-1429,检查defaultValue在异步时是否有异常


); }; LoadDataWithDefaultValueDemo.parameters = { chromatic: { disableSnapshot: false }, } export const OnChangeWithObject = () => ( <>
单选 + onChangeWithObject + defaultValue 为 string []


多选 + onChangeWithObject + defaultValue 为 string []


单选 + onChangeWithObject + defaultValue 为 object []


多选 + onChangeWithObject + defaultValue 为 object []
); export const undefinedValueWhileMutipleAndOnChangeWithObject = () => { const [value, setValue] = useState(undefined); return ( <>
多选 + onChangeWithObject + value 为 undefined
{ setValue(v); }} /> ) } export const LeafOnly = () => { const [value, setValue] = useState([]) return (
autoMergeValue=false,leafOnly=false


autoMergeValue=false,leafOnly=true, leafOnly生效


受控,autoMergeValue=false,leafOnly=true, leafOnly生效
{ console.log(v); setValue(v) }} autoMergeValue={false} leafOnly={true} value={value} />

受控 onChangeWithObject, autoMergeValue=false,leafOnly=true, leafOnly生效
{ console.log(v); setValue(v) }} onChangeWithObject autoMergeValue={false} leafOnly={true} value={value} />

autoMergeValue=true,leafOnly=false



autoMergeValue=true,leafOnly=true
); } export const DynamicTreeData = () => { const [treeDataDemo1,setTreeData1]=useState(treeData2); const [treeDataDemo2,setTreeData2]=useState(treeData2); const [treeDataDemo3,setTreeData3]=useState(treeData2); const [treeDataDemo4,setTreeData4]=useState(treeData2); const [treeDataDemo5,setTreeData5]=useState(treeData2); const [value3,setValue3]=useState(); const [value4,setValue4]=useState(); return (
多选 + 动态更新 tree


单选 + 动态更新 tree


多选 + 动态更新 tree + 受控
{ console.log(v); setValue3(v); }} placeholder="请选择所在地区" />

单选 + 动态更新 tree + 受控
{ console.log(v); setValue4(v); }} placeholder="请选择所在地区" />

多选 + 动态更新 tree + defaultValue 为亚洲


); } export const SuperLongList = () => { let treeData = new Array(100).fill().map(() => ({ label: '浙江省', value: 'zhejiang' })); treeData.push({ label: '到底啦', value: 'bottom' }) return ( {console.log(123)}} /> ); };