mirror of
				https://github.com/reduxjs/redux-devtools.git
				synced 2025-11-04 09:57:26 +03:00 
			
		
		
		
	support for state with iterable structures
This commit is contained in:
		
							parent
							
								
									b09d171f2d
								
							
						
					
					
						commit
						56de89c440
					
				
							
								
								
									
										141
									
								
								src/react/JSONTree/JSONIterableNode.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								src/react/JSONTree/JSONIterableNode.js
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,141 @@
 | 
				
			||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					import reactMixin from 'react-mixin';
 | 
				
			||||||
 | 
					import { ExpandedStateHandlerMixin } from './mixins';
 | 
				
			||||||
 | 
					import JSONArrow from './JSONArrow';
 | 
				
			||||||
 | 
					import grabNode from './grab-node';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const styles = {
 | 
				
			||||||
 | 
					  base: {
 | 
				
			||||||
 | 
					    position: 'relative',
 | 
				
			||||||
 | 
					    paddingTop: 3,
 | 
				
			||||||
 | 
					    paddingBottom: 3,
 | 
				
			||||||
 | 
					    paddingRight: 0,
 | 
				
			||||||
 | 
					    marginLeft: 14
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  label: {
 | 
				
			||||||
 | 
					    margin: 0,
 | 
				
			||||||
 | 
					    padding: 0,
 | 
				
			||||||
 | 
					    display: 'inline-block'
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  span: {
 | 
				
			||||||
 | 
					    cursor: 'default'
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  spanType: {
 | 
				
			||||||
 | 
					    marginLeft: 5,
 | 
				
			||||||
 | 
					    marginRight: 5
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@reactMixin.decorate(ExpandedStateHandlerMixin)
 | 
				
			||||||
 | 
					export default class JSONIterableNode extends React.Component {
 | 
				
			||||||
 | 
					  defaultProps = {
 | 
				
			||||||
 | 
					    data: [],
 | 
				
			||||||
 | 
					    initialExpanded: false
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // flag to see if we still need to render our child nodes
 | 
				
			||||||
 | 
					  needsChildNodes = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // cache store for our child nodes
 | 
				
			||||||
 | 
					  renderedChildren = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // cache store for the number of items string we display
 | 
				
			||||||
 | 
					  itemString = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  constructor(props) {
 | 
				
			||||||
 | 
					    super(props);
 | 
				
			||||||
 | 
					    this.state = {
 | 
				
			||||||
 | 
					      expanded: this.props.initialExpanded,
 | 
				
			||||||
 | 
					      createdChildNodes: false
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Returns the child nodes for each element in the array. If we have
 | 
				
			||||||
 | 
					  // generated them previously, we return from cache, otherwise we create
 | 
				
			||||||
 | 
					  // them.
 | 
				
			||||||
 | 
					  getChildNodes() {
 | 
				
			||||||
 | 
					    if (this.state.expanded && this.needsChildNodes) {
 | 
				
			||||||
 | 
					      let childNodes = [];
 | 
				
			||||||
 | 
					      for (const entry of this.props.data) {
 | 
				
			||||||
 | 
					        let key = null;
 | 
				
			||||||
 | 
					        let value = null;
 | 
				
			||||||
 | 
					        if (Array.isArray(entry)) {
 | 
				
			||||||
 | 
					          [key, value] = entry;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          key = childNodes.length;
 | 
				
			||||||
 | 
					          value = entry;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let prevData;
 | 
				
			||||||
 | 
					        if (typeof this.props.previousData !== 'undefined') {
 | 
				
			||||||
 | 
					          prevData = this.props.previousData[key];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        const node = grabNode(key, value, prevData, this.props.theme);
 | 
				
			||||||
 | 
					        if (node !== false) {
 | 
				
			||||||
 | 
					          childNodes.push(node);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      this.needsChildNodes = false;
 | 
				
			||||||
 | 
					      this.renderedChildren = childNodes;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return this.renderedChildren;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Returns the "n Items" string for this node, generating and
 | 
				
			||||||
 | 
					  // caching it if it hasn't been created yet.
 | 
				
			||||||
 | 
					  getItemString() {
 | 
				
			||||||
 | 
					    if (!this.itemString) {
 | 
				
			||||||
 | 
					      const { data } = this.props;
 | 
				
			||||||
 | 
					      let count = 0;
 | 
				
			||||||
 | 
					      if (typeof data.count === 'function') {
 | 
				
			||||||
 | 
					        count = data.count();
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        count = data.length;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      this.itemString = count + ' entr' + (count !== 1 ? 'ies' : 'y');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return this.itemString;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  render() {
 | 
				
			||||||
 | 
					    const childNodes = this.getChildNodes();
 | 
				
			||||||
 | 
					    const childListStyle = {
 | 
				
			||||||
 | 
					      padding: 0,
 | 
				
			||||||
 | 
					      margin: 0,
 | 
				
			||||||
 | 
					      listStyle: 'none',
 | 
				
			||||||
 | 
					      display: (this.state.expanded) ? 'block' : 'none'
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    let containerStyle;
 | 
				
			||||||
 | 
					    let spanStyle = {
 | 
				
			||||||
 | 
					      ...styles.span,
 | 
				
			||||||
 | 
					      color: this.props.theme.base0E
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    containerStyle = {
 | 
				
			||||||
 | 
					      ...styles.base
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    if (this.state.expanded) {
 | 
				
			||||||
 | 
					      spanStyle = {
 | 
				
			||||||
 | 
					        ...spanStyle,
 | 
				
			||||||
 | 
					        color: this.props.theme.base03
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					      <li style={containerStyle}>
 | 
				
			||||||
 | 
					        <JSONArrow theme={this.props.theme} open={this.state.expanded} onClick={::this.handleClick}/>
 | 
				
			||||||
 | 
					        <label style={{
 | 
				
			||||||
 | 
					          ...styles.label,
 | 
				
			||||||
 | 
					          color: this.props.theme.base0D
 | 
				
			||||||
 | 
					        }} onClick={::this.handleClick}>
 | 
				
			||||||
 | 
					          {this.props.keyName}:
 | 
				
			||||||
 | 
					        </label>
 | 
				
			||||||
 | 
					        <span style={spanStyle} onClick={::this.handleClick}>
 | 
				
			||||||
 | 
					          <span style={styles.spanType}>()</span>
 | 
				
			||||||
 | 
					          {this.getItemString()}
 | 
				
			||||||
 | 
					        </span>
 | 
				
			||||||
 | 
					        <ol style={childListStyle}>
 | 
				
			||||||
 | 
					          {childNodes}
 | 
				
			||||||
 | 
					        </ol>
 | 
				
			||||||
 | 
					      </li>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@ import React from 'react';
 | 
				
			||||||
import objType from './obj-type';
 | 
					import objType from './obj-type';
 | 
				
			||||||
import JSONObjectNode from './JSONObjectNode';
 | 
					import JSONObjectNode from './JSONObjectNode';
 | 
				
			||||||
import JSONArrayNode from './JSONArrayNode';
 | 
					import JSONArrayNode from './JSONArrayNode';
 | 
				
			||||||
 | 
					import JSONIterableNode from './JSONIterableNode';
 | 
				
			||||||
import JSONStringNode from './JSONStringNode';
 | 
					import JSONStringNode from './JSONStringNode';
 | 
				
			||||||
import JSONNumberNode from './JSONNumberNode';
 | 
					import JSONNumberNode from './JSONNumberNode';
 | 
				
			||||||
import JSONBooleanNode from './JSONBooleanNode';
 | 
					import JSONBooleanNode from './JSONBooleanNode';
 | 
				
			||||||
| 
						 | 
					@ -13,6 +14,8 @@ export default function(key, value, prevValue, theme) {
 | 
				
			||||||
    return <JSONObjectNode data={value} previousData={prevValue} theme={theme} keyName={key} key={key} />;
 | 
					    return <JSONObjectNode data={value} previousData={prevValue} theme={theme} keyName={key} key={key} />;
 | 
				
			||||||
  } else if (nodeType === 'Array') {
 | 
					  } else if (nodeType === 'Array') {
 | 
				
			||||||
    return <JSONArrayNode data={value} previousData={prevValue} theme={theme} keyName={key} key={key} />;
 | 
					    return <JSONArrayNode data={value} previousData={prevValue} theme={theme} keyName={key} key={key} />;
 | 
				
			||||||
 | 
					  } else if (nodeType === 'Iterable') {
 | 
				
			||||||
 | 
					    return <JSONIterableNode data={value} previousData={prevValue} theme={theme} keyName={key} key={key} />;
 | 
				
			||||||
  } else if (nodeType === 'String') {
 | 
					  } else if (nodeType === 'String') {
 | 
				
			||||||
    return <JSONStringNode keyName={key} previousValue={prevValue} theme={theme} value={value} key={key} />;
 | 
					    return <JSONStringNode keyName={key} previousValue={prevValue} theme={theme} value={value} key={key} />;
 | 
				
			||||||
  } else if (nodeType === 'Number') {
 | 
					  } else if (nodeType === 'Number') {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,7 @@
 | 
				
			||||||
export default function(obj) {
 | 
					export default function(obj) {
 | 
				
			||||||
  return Object.prototype.toString.call(obj).slice(8, -1);
 | 
					  const type = Object.prototype.toString.call(obj).slice(8, -1);
 | 
				
			||||||
 | 
					  if (type === 'Object' && typeof obj[Symbol.iterator] === 'function') {
 | 
				
			||||||
 | 
					    return 'Iterable';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return type;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user