1
0

nodeList.tsx 3.2 KB

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