Consider a question: how to get the next level data set of Hebei and Tianjin?

↓↓↓ Tree structure

const tree = [
    {
        value: '1'.name: 'hebei'.children: [{value: '10'.name: 'cangzhou'.children: [{value: '101'.name: 'cangxian' },
                    { value: '102'.name: 'to potow' },
                    { value: '103'.name: 'hengshui'}}]}, {value: '2'.name: 'Beijing'.children: [{value: '20'.name: 'Chaoyang district'},
            { value: '21'.name: 'West Town'}, {value: '22'.name: 'Dongcheng District',}]}, {value: '3'.name: 'tianjin'.children: [{value: 'and'.name: 'Wuqing District'},
            { value: '32'.name: 'Jinnan District' },
            { value: '33'.name: 'Tianjin North'}}]]Copy the code

Let me guess what you think

Through the filter to filter out name = = tianjin | | name = = hebei?

If you think the same way, how to deal with the information of cangzhou at the next level?

In the tree structure, we operate elements is very complex, requires a lot of loops and recursion, each search to traverse, children to find the parent is also very tedious, how to once and for all? Can the converted data result be called later after being converted once?

What data structure gives you the best way to get a property?

Object {}

How do I convert tree structures into objects?

We should pay attention to the following three points

  • Keep the original data structure of the tree
  • Attribute uniqueness
  • Parent-child correlation

Find unique value in data structure, value value is unique, can use value as the attribute [key], add attribute parentIds in subset to store all the key of the parent as the associated attribute of the child parent, the transformed data structure is as follows:

{
    "1": {"value":"1"."name":"Hebei"."children":[
            {
                "value":"10"."name":Cangzhou ""."children":[
                    { "value":"101"."name":"Cangxian" },
            	    { "value":"102"."name":"To potow" },
 	            { "value":"103"."name":"Hengshui"}}]]."parentIds": []},"2": {"value":"2"."name":"Beijing"."children":[
            { "value":"20"."name":"Chaoyang District" },
            { "value":"21"."name":"West Side" },
            {  "value":"22"."name":"Dongcheng District"}]."parentIds": []},"3": {"value":"3"."name":"Tianjin"."children":[
            { "value":"31"."name":"Wuqing District" },
            { "value":"32"."name":"Jinnan District" },
            { "value":"33"."name":"Tianjin North"}]."parentIds": []},"10": {"value":"10"."name":Cangzhou ""."children":[
            { "value":"101"."name":"Cangxian" },
            { "value":"102"."name":"To potow" },
 	    { "value":"103"."name":"Hengshui"}]."parentIds": ["1"]},"20": {"value":"20"."name":"Chaoyang District"."parentIds": ["2"]},"21": {"value":"21"."name":"West Side"."parentIds": ["2"]},"22": {"value":"21"."name":"Dongcheng District"."parentIds": ["2"]},"31": {"value":"31"."name":"Wuqing District"."parentIds": ["3"]},"32": {"value":"32"."name":"Jinnan District"."parentIds": ["3"]},"33": {"value":"33"."name":"Tianjin North"."parentIds": ["3"]},"101": {"value":"101"."name":"Cangxian"."parentIds": ["1"."10"]},"102": {"value":"102"."name":"To potow"."parentIds": :"1"."10"]},"103": {"value":"103"."name":"Hengshui"."parentIds": ["1"."10"]}}Copy the code

Convert tree to obj

ParentIds stores values of all parent classes. If there is no parent class, return [].

/** * Convert tree to obj, obj key to value, parentIds to store all parent values, if no parent class returns [] *@param {*} Tree Indicates the tree node *@param {*} ParentIds ID of the parent *@param {*} Obj Result of obj after last processing */
function getObjByTree(tree, parentIds = [], obj = {}) {
// Walk through the tree structure
    for (let i = 0; i < tree.length; i++) {
        const item = tree[i];
        obj[item.value] = {// Set the converted properties and values. item,// Save the current data structure
            parentIds: parentIds // Store all parent ids
        }
        if (item.children) {// Perform the above logic recursively if there is a subset
            getObjByTree(item.children, [...parentIds, item.value], obj)
        }
    }
    return obj
}
Copy the code

The actual case

background

The tree hierarchy is uncertain, and the tree data can be selected to find the lower levels

Results show

Code implementation

The state store is initialized

  • Initial setting
 this.state = {
            treeMapDistance: {},
            selectKeyObj: { 0: { list: [].values: []}}};Copy the code
  • Gets the transformed tree structure and sets the initial value
componentDidMount = () = > {
        let treeMapDistance = getObjByTree(tree)
        this.setState({
            treeMapDistance: treeMapDistance,
            selectKeyObj: { 0: { list: tree, values: []}}})}Copy the code

Page structure

Multi-layer rendering using Object.keys(selectKeyObj)

render() {
        const { selectKeyObj } = this.state
        return (
            <div>
                {(Object.keys(selectKeyObj).map((selectKey, index) => <Select
                    mode="multiple"
                    value={selectKeyObj[selectKey].values}
                    onChange={(values)= > this.setSelectKey(values, index)}
                    key={index}
                    className='multiple-select-item'>
                    {selectKeyObj[selectKey].list.map(one => <Option 
                    value={one.value} 
                    key={one.value}> {one.name} </Option>)}
                </Select>))}
            </div>
 );
Copy the code

Sets the current selected item and the sublist datasetSelectKey

  • Stores the currently selected value and gets the child element, set with responsibilitylistData, no responsibility for setting[]
setSelectKey = (values, key) = > {
        const { selectKeyObj } = this.state
        letselectKeyNew = { ... selectKeyObj }// Add current click data
        selectKeyNew[key] = {
            list: selectKeyObj[key].list,
            values: values
        }
        // Add the next-level list display item
        const nextList = this.getList(values)
        if (nextList.length > 0) {
            selectKeyNew[key + 1] = {
                list: nextList,
                values: []}}this.setState({
            selectKeyObj: selectKeyNew,
        })
}
Copy the code
  • Gets the child element method
 /** * Get the next-level array * based on values@param {*} Values The selected value of the parent element */
    getList = (values) = > {
        const { treeMapDistance } = this.state
        return values.map(item= > treeMapDistance[item].children || []).flat()
    }
Copy the code
  • Results show

Advanced placement process

  • Modify parent, clear subset selection
setSelectKey = (values, key) = > {
    const { selectKeyObj } = this.state
    letselectKeyNew = { ... selectKeyObj }//+++++ add skip level processing begins
    let list = Object.keys(selectKeyObj)// Get the current array
    let children = list.splice(key, list.length)// Get the lower-level data
    for (let i = 0; i < children.length; i++) {// Clear the lower-level data
        const key = children[i];
        delete selectKeyNew[key]
    }
    //+++++ Add skip level no further action is required
    // Add current click data
    selectKeyNew[key] = {
        list: selectKeyObj[key].list,
        values: values
}
....
Copy the code
  • Results the following