Switching to use React.createRef

This commit is contained in:
Jeff Avallone 2018-03-31 11:44:26 -04:00
parent f5f30a854b
commit f0062c94be
8 changed files with 52 additions and 40 deletions

View File

@ -114,8 +114,8 @@ class App extends React.PureComponent {
expr expr
}, async () => { }, async () => {
await this.image.doReflow(); await this.image.doReflow();
this.setSvgUrl(this.image.svg); this.setSvgUrl(this.image.svg.current);
this.setPngUrl(this.image.svg); this.setPngUrl(this.image.svg.current);
}); });
} }

View File

@ -12,10 +12,14 @@ class Box extends React.PureComponent {
radius: 3 radius: 3
} }
label = React.createRef()
children = [React.createRef()]
reflow() { reflow() {
const { padding, useAnchors } = this.props; const { padding, useAnchors } = this.props;
const box = this.children[0].getBBox(); const box = this.children[0].current.getBBox();
const labelBox = this.label ? this.label.getBBox() : { width: 0, height: 0}; const labelBox = this.label.current ? this.label.current.getBBox() : { width: 0, height: 0};
this.setBBox({ this.setBBox({
width: Math.max(box.width + 2 * padding, labelBox.width), width: Math.max(box.width + 2 * padding, labelBox.width),
@ -34,10 +38,6 @@ class Box extends React.PureComponent {
}); });
} }
containedRef = contained => this.children = [contained]
labelRef = label => this.label = label
render() { render() {
const { theme, radius, label, children } = this.props; const { theme, radius, label, children } = this.props;
const { width, height, labelTransform, rectTransform, contentTransform } = this.state || {}; const { width, height, labelTransform, rectTransform, contentTransform } = this.state || {};
@ -53,7 +53,7 @@ class Box extends React.PureComponent {
const textProps = { const textProps = {
transform: labelTransform, transform: labelTransform,
style: style.infoText, style: style.infoText,
ref: this.labelRef ref: this.label
}; };
return <React.Fragment> return <React.Fragment>
@ -61,7 +61,7 @@ class Box extends React.PureComponent {
{ label && <text { ...textProps }>{ label }</text> } { label && <text { ...textProps }>{ label }</text> }
<g transform={ contentTransform }> <g transform={ contentTransform }>
{ React.cloneElement(React.Children.only(children), { { React.cloneElement(React.Children.only(children), {
ref: this.containedRef ref: this.children[0]
}) } }) }
</g> </g>
</React.Fragment>; </React.Fragment>;

View File

@ -18,6 +18,8 @@ class HorizontalLayout extends React.PureComponent {
childTransforms: List() childTransforms: List()
} }
children = []
updateChildTransforms(childBoxes) { updateChildTransforms(childBoxes) {
return this.state.childTransforms.withMutations(transforms => ( return this.state.childTransforms.withMutations(transforms => (
childBoxes.forEach((box, i) => ( childBoxes.forEach((box, i) => (
@ -44,7 +46,7 @@ class HorizontalLayout extends React.PureComponent {
reflow() { reflow() {
const { spacing, withConnectors } = this.props; const { spacing, withConnectors } = this.props;
const childBoxes = this.children.map(child => child.getBBox()); const childBoxes = this.children.map(child => child.current.getBBox());
const verticalCenter = childBoxes.reduce((center, box) => Math.max(center, box.axisY), 0); const verticalCenter = childBoxes.reduce((center, box) => Math.max(center, box.axisY), 0);
const width = childBoxes.reduce((width, box) => width + box.width, 0) + (childBoxes.length - 1) * spacing; const width = childBoxes.reduce((width, box) => width + box.width, 0) + (childBoxes.length - 1) * spacing;
const height = childBoxes.reduce((ascHeight, box) => Math.max(ascHeight, box.axisY), 0) + const height = childBoxes.reduce((ascHeight, box) => Math.max(ascHeight, box.axisY), 0) +
@ -64,20 +66,18 @@ class HorizontalLayout extends React.PureComponent {
}); });
} }
childRef = i => child => this.children[i] = child
render() { render() {
const { children } = this.props; const { children } = this.props;
const { childTransforms, connectorPaths } = this.state; const { childTransforms, connectorPaths } = this.state;
this.children = []; this.makeRefCollection(this.children, React.Children.count(children));
return <React.Fragment> return <React.Fragment>
<path d={ connectorPaths } style={ style.connectors }></path> <path d={ connectorPaths } style={ style.connectors }></path>
{ React.Children.map(children, (child, i) => ( { React.Children.map(children, (child, i) => (
<g transform={ childTransforms.get(i) }> <g transform={ childTransforms.get(i) }>
{ React.cloneElement(child, { { React.cloneElement(child, {
ref: this.childRef(i) ref: this.children[i]
}) } }) }
</g> </g>
))} ))}

View File

@ -31,9 +31,13 @@ class Image extends React.PureComponent {
height: 0 height: 0
} }
svg = React.createRef()
children = [React.createRef()]
reflow() { reflow() {
const { padding } = this.props; const { padding } = this.props;
const box = this.children[0].getBBox(); const box = this.children[0].current.getBBox();
this.setStateAsync({ this.setStateAsync({
width: Math.round(box.width + 2 * padding), width: Math.round(box.width + 2 * padding),
@ -41,10 +45,6 @@ class Image extends React.PureComponent {
}); });
} }
containedRef = contained => this.children = [contained]
svgRef = svg => this.svg = svg
render() { render() {
const { width, height } = this.state; const { width, height } = this.state;
const { padding, children } = this.props; const { padding, children } = this.props;
@ -54,7 +54,7 @@ class Image extends React.PureComponent {
height, height,
viewBox: [0, 0, width, height].join(' '), viewBox: [0, 0, width, height].join(' '),
style: style.image, style: style.image,
ref: this.svgRef, ref: this.svg,
...namespaceProps ...namespaceProps
}; };
@ -62,7 +62,7 @@ class Image extends React.PureComponent {
<metadata dangerouslySetInnerHTML={{ __html: metadata }}></metadata> <metadata dangerouslySetInnerHTML={{ __html: metadata }}></metadata>
<g transform={ `translate(${ padding } ${ padding })` }> <g transform={ `translate(${ padding } ${ padding })` }>
{ React.cloneElement(React.Children.only(children), { { React.cloneElement(React.Children.only(children), {
ref: this.containedRef ref: this.children[0]
}) } }) }
</g> </g>
</svg>; </svg>;

View File

@ -57,6 +57,10 @@ const repeatPath = (box, greedy) => {
@reflowable @reflowable
class Loop extends React.PureComponent { class Loop extends React.PureComponent {
label = React.createRef()
children = [React.createRef()]
get contentOffset() { get contentOffset() {
const { skip, repeat } = this.props; const { skip, repeat } = this.props;
@ -71,8 +75,8 @@ class Loop extends React.PureComponent {
reflow() { reflow() {
const { skip, repeat, greedy } = this.props; const { skip, repeat, greedy } = this.props;
const box = this.children[0].getBBox(); const box = this.children[0].current.getBBox();
const labelBox = this.label ? this.label.getBBox() : { width: 0, height: 0 }; const labelBox = this.label.current ? this.label.current.getBBox() : { width: 0, height: 0 };
let height = box.height + labelBox.height; let height = box.height + labelBox.height;
if (skip) { if (skip) {
@ -102,10 +106,6 @@ class Loop extends React.PureComponent {
}); });
} }
containedRef = contained => this.children = [contained]
labelRef = label => this.label = label
render() { render() {
const { label, children } = this.props; const { label, children } = this.props;
const { loopPaths, labelTransform } = this.state || {}; const { loopPaths, labelTransform } = this.state || {};
@ -113,7 +113,7 @@ class Loop extends React.PureComponent {
const textProps = { const textProps = {
transform: labelTransform, transform: labelTransform,
style: style.infoText, style: style.infoText,
ref: this.labelRef ref: this.label
}; };
return <React.Fragment> return <React.Fragment>
@ -121,7 +121,7 @@ class Loop extends React.PureComponent {
{ label && <text { ...textProps }>{ label }</text> } { label && <text { ...textProps }>{ label }</text> }
<g transform={ `translate(${ this.contentOffset.x } ${ this.contentOffset.y })` }> <g transform={ `translate(${ this.contentOffset.x } ${ this.contentOffset.y })` }>
{ React.cloneElement(React.Children.only(children), { { React.cloneElement(React.Children.only(children), {
ref: this.containedRef ref: this.children[0]
}) } }) }
</g> </g>
</React.Fragment>; </React.Fragment>;

View File

@ -7,8 +7,10 @@ import reflowable from './reflowable';
@reflowable @reflowable
class Text extends React.PureComponent { class Text extends React.PureComponent {
text = React.createRef()
reflow() { reflow() {
const box = this.text.getBBox(); const box = this.text.current.getBBox();
this.setBBox({ this.setBBox({
width: box.width, width: box.width,
@ -20,8 +22,6 @@ class Text extends React.PureComponent {
}); });
} }
textRef = text => this.text = text
renderContent() { renderContent() {
const { children, quoted } = this.props; const { children, quoted } = this.props;
if (!quoted) { if (!quoted) {
@ -42,7 +42,7 @@ class Text extends React.PureComponent {
const textProps = { const textProps = {
style: { ...style.text, ...style[theme] }, style: { ...style.text, ...style[theme] },
transform, transform,
ref: this.textRef ref: this.text
}; };
return <text { ...textProps }> return <text { ...textProps }>

View File

@ -20,6 +20,8 @@ class VerticalLayout extends React.PureComponent {
childTransforms: List() childTransforms: List()
} }
children = []
updateChildTransforms(childBoxes) { updateChildTransforms(childBoxes) {
return this.state.childTransforms.withMutations(transforms => ( return this.state.childTransforms.withMutations(transforms => (
childBoxes.forEach((box, i) => ( childBoxes.forEach((box, i) => (
@ -82,7 +84,7 @@ class VerticalLayout extends React.PureComponent {
reflow() { reflow() {
const { spacing, withConnectors } = this.props; const { spacing, withConnectors } = this.props;
const childBoxes = this.children.map(child => child.getBBox()); const childBoxes = this.children.map(child => child.current.getBBox());
const horizontalCenter = childBoxes.reduce((center, box) => Math.max(center, box.width / 2), 0); const horizontalCenter = childBoxes.reduce((center, box) => Math.max(center, box.width / 2), 0);
const margin = withConnectors ? connectorMargin : 0; const margin = withConnectors ? connectorMargin : 0;
const width = childBoxes.reduce((width, box) => Math.max(width, box.width), 0) + 2 * margin; const width = childBoxes.reduce((width, box) => Math.max(width, box.width), 0) + 2 * margin;
@ -106,20 +108,18 @@ class VerticalLayout extends React.PureComponent {
}); });
} }
childRef = i => child => this.children[i] = child
render() { render() {
const { children } = this.props; const { children } = this.props;
const { childTransforms, connectorPaths } = this.state; const { childTransforms, connectorPaths } = this.state;
this.children = []; this.makeRefCollection(this.children, React.Children.count(children));
return <React.Fragment> return <React.Fragment>
<path d={ connectorPaths } style={ style.connectors }></path> <path d={ connectorPaths } style={ style.connectors }></path>
{ React.Children.map(children, (child, i) => ( { React.Children.map(children, (child, i) => (
<g transform={ childTransforms.get(i) }> <g transform={ childTransforms.get(i) }>
{ React.cloneElement(child, { { React.cloneElement(child, {
ref: this.childRef(i) ref: this.children[i]
}) } }) }
</g> </g>
)) } )) }

View File

@ -1,3 +1,4 @@
import React from 'react';
import { Map } from 'immutable'; import { Map } from 'immutable';
const reflowable = Component => { const reflowable = Component => {
@ -46,13 +47,24 @@ const reflowable = Component => {
}; };
}, },
makeRefCollection(collection, count) {
const diff = Math.abs(collection.length - count);
if (collection.length < count) {
const fill = Array.apply(null, new Array(diff)).map(() => React.createRef());
collection.splice.apply(collection, [collection.length, diff, ...fill]);
} else if (collection.length > count) {
collection.splice(collection.length - diff, diff);
}
},
async reflowChildren() { async reflowChildren() {
// No child components // No child components
if (this.children === undefined) { if (this.children === undefined) {
return true; return true;
} }
const reflowed = await Promise.all(this.children.map(c => c.doReflow())); const reflowed = await Promise.all(this.children.map(c => c.current.doReflow()));
return reflowed.reduce((memo, value) => memo || value, false); return reflowed.reduce((memo, value) => memo || value, false);
}, },