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
}, async () => {
await this.image.doReflow();
this.setSvgUrl(this.image.svg);
this.setPngUrl(this.image.svg);
this.setSvgUrl(this.image.svg.current);
this.setPngUrl(this.image.svg.current);
});
}

View File

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

View File

@ -18,6 +18,8 @@ class HorizontalLayout extends React.PureComponent {
childTransforms: List()
}
children = []
updateChildTransforms(childBoxes) {
return this.state.childTransforms.withMutations(transforms => (
childBoxes.forEach((box, i) => (
@ -44,7 +46,7 @@ class HorizontalLayout extends React.PureComponent {
reflow() {
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 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) +
@ -64,20 +66,18 @@ class HorizontalLayout extends React.PureComponent {
});
}
childRef = i => child => this.children[i] = child
render() {
const { children } = this.props;
const { childTransforms, connectorPaths } = this.state;
this.children = [];
this.makeRefCollection(this.children, React.Children.count(children));
return <React.Fragment>
<path d={ connectorPaths } style={ style.connectors }></path>
{ React.Children.map(children, (child, i) => (
<g transform={ childTransforms.get(i) }>
{ React.cloneElement(child, {
ref: this.childRef(i)
ref: this.children[i]
}) }
</g>
))}

View File

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

View File

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

View File

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

View File

@ -20,6 +20,8 @@ class VerticalLayout extends React.PureComponent {
childTransforms: List()
}
children = []
updateChildTransforms(childBoxes) {
return this.state.childTransforms.withMutations(transforms => (
childBoxes.forEach((box, i) => (
@ -82,7 +84,7 @@ class VerticalLayout extends React.PureComponent {
reflow() {
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 margin = withConnectors ? connectorMargin : 0;
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() {
const { children } = this.props;
const { childTransforms, connectorPaths } = this.state;
this.children = [];
this.makeRefCollection(this.children, React.Children.count(children));
return <React.Fragment>
<path d={ connectorPaths } style={ style.connectors }></path>
{ React.Children.map(children, (child, i) => (
<g transform={ childTransforms.get(i) }>
{ React.cloneElement(child, {
ref: this.childRef(i)
ref: this.children[i]
}) }
</g>
)) }

View File

@ -1,3 +1,4 @@
import React from 'react';
import { Map } from 'immutable';
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() {
// No child components
if (this.children === undefined) {
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);
},