nodeList.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import React, { PureComponent } from 'react';
  2. import { isEqual } from 'lodash';
  3. import TreeContext from './treeContext';
  4. import { FlattenNode, NodeListProps, NodeListState, TransitionNodes } from './interface';
  5. import NodeCollapsible from './nodeCollapsible';
  6. const getTreeNodeKey = (treeNode: FlattenNode) => {
  7. return treeNode.key;
  8. };
  9. export default class NodeList extends PureComponent<NodeListProps, NodeListState> {
  10. static contextType = TreeContext;
  11. constructor(props: NodeListProps) {
  12. super(props);
  13. this.state = {
  14. transitionNodes: [],
  15. };
  16. }
  17. static getDerivedStateFromProps(props: NodeListProps, prevState: NodeListState) {
  18. const { flattenNodes = [], motionKeys, motionType, flattenList = [] } = props;
  19. const hasChanged = !isEqual(prevState.cachedMotionKeys, motionKeys) ||
  20. !isEqual(prevState.cachedData.map(i => i.key), flattenNodes.map(i => i.key));
  21. const motionArr = [...motionKeys];
  22. if (!hasChanged || !motionArr.length) {
  23. return null;
  24. }
  25. const transitionNodes: TransitionNodes<FlattenNode> = [];
  26. const transitionRange: FlattenNode[] = [];
  27. let rangeStart = 0;
  28. let newState = {};
  29. const lookUpTarget = motionType === 'hide' && flattenList ? flattenList : flattenNodes;
  30. lookUpTarget.forEach((treeNode, ind) => {
  31. const nodeKey = getTreeNodeKey(treeNode);
  32. if (motionKeys.has(nodeKey)) {
  33. transitionRange.push(treeNode);
  34. if (nodeKey === motionArr[0]) {
  35. rangeStart = ind;
  36. }
  37. } else {
  38. transitionNodes.push(treeNode);
  39. }
  40. });
  41. transitionNodes.splice(rangeStart, 0, transitionRange);
  42. newState = {
  43. transitionNodes,
  44. cachedData: flattenNodes,
  45. cachedMotionKeys: motionKeys,
  46. cachedMotionType: motionType
  47. };
  48. return newState;
  49. }
  50. onMotionEnd = () => {
  51. typeof this.props.onMotionEnd === 'function' && this.props.onMotionEnd();
  52. this.setState({ transitionNodes: [] });
  53. };
  54. render() {
  55. const { flattenNodes, motionType, searchTargetIsDeep, renderTreeNode } = this.props;
  56. const { transitionNodes } = this.state;
  57. const mapData = transitionNodes.length && !searchTargetIsDeep ? transitionNodes : flattenNodes;
  58. const options = mapData.map(treeNode => {
  59. const isMotionNode = Array.isArray(treeNode);
  60. if (isMotionNode && !(treeNode as FlattenNode[]).length) {
  61. return null;
  62. }
  63. if (isMotionNode && (treeNode as FlattenNode[]).length) {
  64. const nodeKey = getTreeNodeKey(treeNode[0]);
  65. return (
  66. <NodeCollapsible
  67. open={motionType === 'hide'}
  68. duration={200}
  69. motion={Boolean(motionType)}
  70. key={`motion-${nodeKey}`}
  71. onMotionEnd={this.onMotionEnd}
  72. >
  73. {treeNode.map(node => renderTreeNode(node))}
  74. </NodeCollapsible>
  75. );
  76. }
  77. return renderTreeNode(treeNode as FlattenNode);
  78. });
  79. return options;
  80. }
  81. }