Repository: element-plus/element-plus
File: packages/components/cascader-panel/src/index.vue (Vue)

Code before:
  } else {
    syncCheckedValue(false, true)
  }
}

const lazyLoad: ElCascaderPanelContext['lazyLoad'] = (node, cb) => {
  const cfg = config.value
  node! = node || new Node({}, cfg, undefined, true)
  node.loading = true

  const resolve = (dataList?: CascaderOption[]) => {
    const _node = node as Node
    const parent = _node.root ? null : _node
    _node.loading = false
    _node.loaded = true
    _node.childrenData = _node.childrenData || []
    dataList && store?.appendNodes(dataList, parent as Node)
    dataList && cb?.(dataList)
  }

  const reject = () => {
    node!.loading = false
    node!.loaded = false
  }

  cfg.lazyLoad(node, resolve, reject)
}

const expandNode: ElCascaderPanelContext['expandNode'] = (node, silent) => {
  const { level } = node
  const newMenus = menus.value.slice(0, level)
  let newExpandingNode: CascaderNode

  if (node.isLeaf) {
    newExpandingNode = node.pathNodes[level - 2]
  } else {
    newExpandingNode = node
    newMenus.push(node.children)
  }

  if (expandingNode.value?.uid !== newExpandingNode?.uid) {
    expandingNode.value = node
    menus.value = newMenus
    !silent && emit('expand-change', node?.pathValues || [])
  }
}

const handleCheckChange: ElCascaderPanelContext['handleCheckChange'] = (
  node,
  checked,
  emitClose = true

Review comment (suggestion):
The loading state is stuck when rejecting the initial nodes, [play](https://element-plus.run/#eyJBcHAudnVlIjoiPHRlbXBsYXRlPlxuICA8ZWwtY2FzY2FkZXIgOnByb3BzPVwicHJvcHNcIiAvPlxuPC90ZW1wbGF0ZT5cblxuPHNjcmlwdCBsYW5nPVwidHNcIiBzZXR1cD5cbmltcG9ydCB0eXBlIHsgQ2FzY2FkZXJQcm9wcyB9IGZyb20gJ2VsZW1lbnQtcGx1cydcblxubGV0IGlkID0gMFxuY29uc3QgcHJvcHM6IENhc2NhZGVyUHJvcHMgPSB7XG4gIGxhenk6IHRydWUsXG4gIGxhenlMb2FkKG5vZGUsIHJlc29sdmUsIHJlamVjdCkge1xuICAgIGNvbnN0IHsgbGV2ZWwgfSA9IG5vZGVcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIGNvbnN0IG5vZGVzID0gQXJyYXkuZnJvbSh7IGxlbmd0aDogbGV2ZWwgKyAxIH0pLm1hcCgoaXRlbSkgPT4gKHtcbiAgICAgICAgdmFsdWU6ICsraWQsXG4gICAgICAgIGxhYmVsOiBgT3B0aW9uIC0gJHtpZH1gLFxuICAgICAgICBsZWFmOiBsZXZlbCA+PSAyLFxuICAgICAgfSkpXG4gICAgICByZWplY3QoKVxuICAgICAgcmV0dXJuXG4gICAgICAvLyBJbnZva2UgYHJlc29sdmVgIGNhbGxiYWNrIHRvIHJldHVybiB0aGUgY2hpbGQgbm9kZXMgZGF0YSBhbmQgaW5kaWNhdGUgdGhlIGxvYWRpbmcgaXMgZmluaXNoZWQuXG4gICAgICByZXNvbHZlKG5vZGVzKVxuICAgIH0sIDEwMDApXG4gIH0sXG59XG48L3NjcmlwdD5cbiIsImVsZW1lbnQtcGx1cy5qcyI6ImltcG9ydCBFbGVtZW50UGx1cyBmcm9tICdlbGVtZW50LXBsdXMnXG5pbXBvcnQgeyBnZXRDdXJyZW50SW5zdGFuY2UgfSBmcm9tICd2dWUnXG5cbmxldCBpbnN0YWxsZWQgPSBmYWxzZVxuYXdhaXQgbG9hZFN0eWxlKClcblxuZXhwb3J0IGZ1bmN0aW9uIHNldHVwRWxlbWVudFBsdXMoKSB7XG4gIGlmIChpbnN0YWxsZWQpIHJldHVyblxuICBjb25zdCBpbnN0YW5jZSA9IGdldEN1cnJlbnRJbnN0YW5jZSgpXG4gIGluc3RhbmNlLmFwcENvbnRleHQuYXBwLnVzZShFbGVtZW50UGx1cylcbiAgaW5zdGFsbGVkID0gdHJ1ZVxufVxuXG5leHBvcnQgZnVuY3Rpb24gbG9hZFN0eWxlKCkge1xuICBjb25zdCBzdHlsZXMgPSBbJ2h0dHBzOi8vcHJldmlldy0yMjI4My1lbGVtZW50LXBsdXMuc3VyZ2Uuc2gvYnVuZGxlL2Rpc3QvaW5kZXguY3NzJywgJ2h0dHBzOi8vcHJldmlldy0yMjI4My1lbGVtZW50LXBsdXMuc3VyZ2Uuc2gvYnVuZGxlL3RoZW1lLWNoYWxrL2RhcmsvY3NzLXZhcnMuY3NzJ10ubWFwKChzdHlsZSkgPT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBsaW5rID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbGluaycpXG4gICAgICBsaW5rLnJlbCA9ICdzdHlsZXNoZWV0J1xuICAgICAgbGluay5ocmVmID0gc3R5bGVcbiAgICAgIGxpbmsuYWRkRXZlbnRMaXN0ZW5lcignbG9hZCcsIHJlc29sdmUpXG4gICAgICBsaW5rLmFkZEV2ZW50TGlzdGVuZXIoJ2Vycm9yJywgcmVqZWN0KVxuICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmQobGluaylcbiAgICB9KVxuICB9KVxuICByZXR1cm4gUHJvbWlzZS5hbGxTZXR0bGVkKHN0eWxlcylcbn1cbiIsInRzY29uZmlnLmpzb24iOiJ7XG4gIFwiY29tcGlsZXJPcHRpb25zXCI6IHtcbiAgICBcInRhcmdldFwiOiBcIkVTTmV4dFwiLFxuICAgIFwianN4XCI6IFwicHJlc2VydmVcIixcbiAgICBcIm1vZHVsZVwiOiBcIkVTTmV4dFwiLFxuICAgIFwibW9kdWxlUmVzb2x1dGlvblwiOiBcIkJ1bmRsZXJcIixcbiAgICBcInR5cGVzXCI6IFtcImVsZW1lbnQtcGx1cy9nbG9iYWwuZC50c1wiXSxcbiAgICBcImFsbG93SW1wb3J0aW5nVHNFeHRlbnNpb25zXCI6IHRydWUsXG4gICAgXCJhbGxvd0pzXCI6IHRydWUsXG4gICAgXCJjaGVja0pzXCI6IHRydWVcbiAgfSxcbiAgXCJ2dWVDb21waWxlck9wdGlvbnNcIjoge1xuICAgIFwidGFyZ2V0XCI6IDMuM1xuICB9XG59XG4iLCJQbGF5Z3JvdW5kTWFpbi52dWUiOiI8c2NyaXB0IHNldHVwPlxuaW1wb3J0IEFwcCBmcm9tICcuL0FwcC52dWUnXG5pbXBvcnQgeyBzZXR1cEVsZW1lbnRQbHVzIH0gZnJvbSAnLi9lbGVtZW50LXBsdXMuanMnXG5zZXR1cEVsZW1lbnRQbHVzKClcbjwvc2NyaXB0PlxuXG48dGVtcGxhdGU+XG4gIDxBcHAgLz5cbjwvdGVtcGxhdGU+XG4iLCJpbXBvcnQtbWFwLmpzb24iOiJ7XG4gIFwiaW1wb3J0c1wiOiB7XG4gICAgXCJ2dWVcIjogXCJodHRwczovL2Zhc3RseS5qc2RlbGl2ci5uZXQvbnBtL0B2dWUvcnVudGltZS1kb21AbGF0ZXN0L2Rpc3QvcnVudGltZS1kb20uZXNtLWJyb3dzZXIuanNcIixcbiAgICBcIkB2dWUvc2hhcmVkXCI6IFwiaHR0cHM6Ly9mYXN0bHkuanNkZWxpdnIubmV0L25wbS9AdnVlL3NoYXJlZEBsYXRlc3QvZGlzdC9zaGFyZWQuZXNtLWJ1bmRsZXIuanNcIixcbiAgICBcImVsZW1lbnQtcGx1c1wiOiBcImh0dHBzOi8vcHJldmlldy0yMjI4My1lbGVtZW50LXBsdXMuc3VyZ2Uuc2gvYnVuZGxlL2Rpc3QvaW5kZXguZnVsbC5taW4ubWpzXCIsXG4gICAgXCJlbGVtZW50LXBsdXMvXCI6IFwidW5zdXBwb3J0ZWRcIixcbiAgICBcIkBlbGVtZW50LXBsdXMvaWNvbnMtdnVlXCI6IFwiaHR0cHM6Ly9mYXN0bHkuanNkZWxpdnIubmV0L25wbS9AZWxlbWVudC1wbHVzL2ljb25zLXZ1ZUAyL2Rpc3QvaW5kZXgubWluLmpzXCJcbiAgfSxcbiAgXCJzY29wZXNcIjoge31cbn0iLCJfbyI6eyJzaG93SGlkZGVuIjp0cnVlLCJzdHlsZVNvdXJjZSI6Imh0dHBzOi8vcHJldmlldy0yMjI4My1lbGVtZW50LXBsdXMuc3VyZ2Uuc2gvYnVuZGxlL2Rpc3QvaW5kZXguY3NzIn19).

I found doing this is fine but after toggling the popper we should be able to retry again.
```suggestion
  const reject = () => {
  	initialLoaded.value = true
    node!.loading = false
```
Perhaps we may need a new state like `rejected` in order to retry.

Code after:
    })
  } else {
    syncCheckedValue(false, true)
  }
}

const lazyLoad: ElCascaderPanelContext['lazyLoad'] = (node, cb) => {
  const cfg = config.value
  node! = node || new Node({}, cfg, undefined, true)
  node.loading = true

  const resolve = (dataList?: CascaderOption[]) => {
    const _node = node as Node
    const parent = _node.root ? null : _node
    _node.loading = false
    _node.loaded = true
    _node.childrenData = _node.childrenData || []
    dataList && store?.appendNodes(dataList, parent as Node)
    dataList && cb?.(dataList)
    if (node.level === 0) {
      initialLoadedOnce.value = true
    }
  }

  const reject = () => {
    node!.loading = false
    node!.loaded = false
    if (node!.level === 0) {
      initialLoaded.value = true
    }
  }

  cfg.lazyLoad(node, resolve, reject)
}

const expandNode: ElCascaderPanelContext['expandNode'] = (node, silent) => {
  const { level } = node
  const newMenus = menus.value.slice(0, level)
  let newExpandingNode: CascaderNode

  if (node.isLeaf) {
    newExpandingNode = node.pathNodes[level - 2]
  } else {
    newExpandingNode = node
    newMenus.push(node.children)
  }

  if (expandingNode.value?.uid !== newExpandingNode?.uid) {
    expandingNode.value = node
    menus.value = newMenus
    !silent && emit('expand-change', node?.pathValues || [])