Skip to content

Instantly share code, notes, and snippets.

@artyomtrityak
Last active July 22, 2018 09:47
Show Gist options
  • Save artyomtrityak/262ddbadc3492808b15b0202ef744c0c to your computer and use it in GitHub Desktop.
Save artyomtrityak/262ddbadc3492808b15b0202ef744c0c to your computer and use it in GitHub Desktop.
React HOC for D3js to pass width / height to React
import ReactDOM from "react-dom";
import React from "react";
import _ from "lodash";
// --------------------------------
// With width / hegit HOC for D3.js
// --------------------------------
const WithSize = Child =>
class extends React.Component {
state = {
width: null,
height: null
};
constructor(props) {
super(props);
this.setSize = this.setSize.bind(this);
this.setSizeDebounced = _.debounce(this.setSize, 1000);
window.addEventListener("resize", this.setSizeDebounced);
}
componentDidMount() {
this.setSize();
}
componentWillUnmount() {
window.removeEventListener("resize", this.setSizeDebounced);
}
setSize() {
const width = ReactDOM.findDOMNode(this).clientWidth;
const height = ReactDOM.findDOMNode(this).clientHeight;
this.setState({ width, height });
}
render() {
const { width, height } = this.state;
return (
<div style={{ width: "100%", height: "100%" }}>
{width && height ? <Child width={width} height={height} {...this.props} /> : null}
</div>
);
}
};
// --------------------------------
// Usage
// --------------------------------
import React from "react";
import * as d3 from "d3";
import WithSize from "../../shared/with-size";
class Chart1 extends React.Component {
static displayName = "D3Chart";
state = {
data: [...],
scaleX: null,
scaleY: null
};
componentDidMount() {
this.setState({
scaleX: this.createScaleX(),
scaleY: this.createScaleY()
});
}
compomentDidUpdate(prevProps) {
// width / height props from WithSize HOC
if (prevProps.width !== this.props.width || prevProps.height !== this.props.height) {
this.setState({
scaleX: this.createScaleX(),
scaleY: this.createScaleY()
});
}
}
createScaleX() {
return d3
.scaleLinear()
.domain([0, d3.max(this.state.data)])
// width / height props from WithSize HOC
.range([0, this.props.width]);
}
createScaleY() {
return d3
.scaleBand()
.domain(this.state.data)
// width / height props from WithSize HOC
.range([0, this.props.height])
.padding(0.1);
}
render() {
// Render bars, rect etc, use this.state scales
}
}
export default WithSize(HorisontalBarChart1);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment