diff --git a/.eslintrc b/.eslintrc index be727efd6..e91d3b2c9 100644 --- a/.eslintrc +++ b/.eslintrc @@ -19,8 +19,8 @@ "**/dist/", "**/es/" ], - "settings":{ - "react":{ + "settings": { + "react": { "version": "detect" } }, @@ -31,12 +31,14 @@ }, "rules": { "consistent-return": 0, - "max-len": [1, 110, 4], - "max-params": ["error", 6], + "max-params": [ + "error", + 6 + ], "object-curly-spacing": 0, "babel/object-curly-spacing": 2, - "jest/require-top-level-describe":"error", + "jest/require-top-level-describe": "error", "react/prop-types": "off", "prettier/prettier": "warn" } -} +} \ No newline at end of file diff --git a/packages/react-vis/src/plot/xy-plot.js b/packages/react-vis/src/plot/xy-plot.js index ccb503c5a..58ebad8f8 100644 --- a/packages/react-vis/src/plot/xy-plot.js +++ b/packages/react-vis/src/plot/xy-plot.js @@ -20,7 +20,7 @@ import React from 'react'; import PropTypes from 'prop-types'; -import equal from 'deep-equal'; +import equal from 'lodash/isEqual'; import {getCombinedClassName} from 'utils/styling-utils'; @@ -188,6 +188,22 @@ class XYPlot extends React.Component { } }; + _childPropCache = Object.create(null); + + /** + * Memoizes the props of the child. + * This is keyed off of the childs 'key' property or defaults to its index. + * @param {number} index The index of the child + * @param {object} newValues The childs props + */ + _getChildProps(index, newValues) { + const key = newValues.key || `@@series-${index}`; + const cached = this._childPropCache[key]; + if (!equal(cached, newValues)) { + this._childPropCache[key] = {...newValues}; + } + return this._childPropCache[key]; + } /** * Prepare the child components (including series) for rendering. * @returns {Array} Array of child components. @@ -201,6 +217,7 @@ class XYPlot extends React.Component { const children = React.Children.toArray(this.props.children); const seriesProps = getSeriesPropsFromChildren(children); const XYPlotValues = getXYPlotValues(props, children); + return children.map((child, index) => { let dataProps = null; if (seriesProps[index]) { @@ -209,21 +226,26 @@ class XYPlot extends React.Component { const {seriesIndex} = seriesProps[index]; dataProps = {data: data[seriesIndex]}; } - return React.cloneElement(child, { + + const childProps = this._getChildProps(index, { ...dimensions, animation, - ...(dataProps && child.type.prototype && child.type.prototype.render - ? { - ref: ref => - (this[`series${seriesProps[index].seriesIndex}`] = ref) - } - : {}), ...seriesProps[index], ...scaleMixins, ...child.props, ...XYPlotValues[index], ...dataProps }); + + const refProp = + dataProps && child.type.prototype && child.type.prototype.render + ? { + ref: ref => + (this[`series${seriesProps[index].seriesIndex}`] = ref) + } + : {}; + + return React.cloneElement(child, {...childProps, ...refProp}); }); } /** diff --git a/packages/react-vis/src/utils/scales-utils.js b/packages/react-vis/src/utils/scales-utils.js index ccefcf4df..972abdfe6 100644 --- a/packages/react-vis/src/utils/scales-utils.js +++ b/packages/react-vis/src/utils/scales-utils.js @@ -763,6 +763,24 @@ export function extractScalePropsFromProps(props, attributes) { return result; } +const ALL_ATTRIBUTES = [ + 'x', + 'y', + 'radius', + 'angle', + 'color', + 'fill', + 'stroke', + 'opacity', + 'size' +]; + +const defaultScaleProps = ALL_ATTRIBUTES.reduce((result, attr) => { + result[`get${toTitleCase(attr)}`] = d => d[attr]; + result[`get${toTitleCase(attr)}0`] = d => d[`${attr}0`]; + return result; +}, {}); + /** * Extract the missing scale props from the given data and return them as * an object. @@ -776,17 +794,21 @@ export function getMissingScaleProps(props, data, attributes) { const result = {}; // Make sure that the domain is set pad it if specified attributes.forEach(attr => { - if (!props[`get${toTitleCase(attr)}`]) { - result[`get${toTitleCase(attr)}`] = d => d[attr]; + const titleCaseAttr = toTitleCase(attr); + const getKey = `get${titleCaseAttr}`; + const get0Key = `get${titleCaseAttr}0`; + + if (!props[getKey]) { + result[getKey] = defaultScaleProps[getKey]; } - if (!props[`get${toTitleCase(attr)}0`]) { - result[`get${toTitleCase(attr)}0`] = d => d[`${attr}0`]; + if (!props[get0Key]) { + result[get0Key] = defaultScaleProps[get0Key]; } if (!props[`${attr}Domain`]) { result[`${attr}Domain`] = getDomainByAccessor( data, - props[`get${toTitleCase(attr)}`] || result[`get${toTitleCase(attr)}`], - props[`get${toTitleCase(attr)}0`] || result[`get${toTitleCase(attr)}0`], + props[getKey] || result[getKey], + props[get0Key] || result[get0Key], props[`${attr}Type`] ); if (props[`${attr}Padding`]) {