Weitere ähnliche Inhalte Ähnlich wie React + Redux + d3.js (20) Mehr von Teemu Kurppa (7) Kürzlich hochgeladen (20) React + Redux + d3.js3. • Declarative UI Library
• Battle-tested by Facebook
• Component-based
• Inline HTML with JSX
4. • Predictable state management for JS Apps
• Great tooling: logging, hot loading, time travel,…
6. d3 - a lot of good stuff
• Handling data: Scales, Interpolators, Time Intervals, Time & Number formats
• Drawing: Paths, Areas, Shapes, Curves, Axes
• Data Structures for Visualization: Voronoi, Stack, Quadtrees, Polygons
• Drawing maps: Projections, Spherical Math, Geopaths
• Animations and Behaviour: Transitions, Easing, Zooming, Dragging, Forces
7. d3 - problems
• No components: code gets unwieldy very quickly
• State management mixed with UI code
9. d3 class pattern
class D3SeriesBarChart {
constructor(el, props, state) {
// setup code
}
update(el, props, state) {
// data-dependent code
}
}
10. React wrapper for d3
class SeriesBarChart extends Component {
componentDidMount() {
this.chart = new D3SeriesBarChart(this.svg,
this.props,
this.state);
}
componentDidUpdate() {
this.chart.update(this.svg, this.props, this.state);
}
render() {
return (
<svg ref={svg => this.svg = svg}
width={this.props.width}
height={this.props.height}>
</svg>
);
}
}
11. React wrapper for d3
class SeriesBarChart extends Component {
componentDidMount() {
this.chart = new D3SeriesBarChart(this.svg,
this.props,
this.state);
}
componentDidUpdate() {
this.chart.update(this.svg, this.props, this.state);
}
render() {
return (
<svg ref={svg => this.svg = svg}
width={this.props.width}
height={this.props.height}>
</svg>
);
}
}
12. React wrapper for d3
var T = React.PropTypes;
SeriesBarChart.propTypes = {
width: T.number.isRequired,
height: T.number.isRequired,
data: T.shape({
x: T.arrayOf(T.number),
y: T.arrayOf(T.arrayOf(T.number)),
}).isRequired,
mode: T.string.isRequired
}
13. Demo Component
class Demo extends Component {
render() {
return (
<div className={classNames(styles.demo)}>
<form>
{this.makeRadio('grouped', this.props.onSelectGrouped)}
{this.makeRadio('stacked', this.props.onSelectStacked)}
</form>
<SeriesBarChart width={960} height={500}
data={this.props.data}
mode={this.props.mode}/>
<div>
<button onClick={this.props.onGenerateData}>
Generate Data
</button>
</div>
</div>
);
}
// …
}
14. Demo Component
class Demo extends Component {
// …
makeRadio(mode, onChange) {
return (
<label><input type=“radio"
name=“mode"
value={mode}
onChange={onChange}
checked={this.props.mode === mode}/>
{mode}
</label>
)
}
}
15. Redu Reducer
// reducers.js
const initialState = {
data: createData(),
mode: 'grouped'
};
function demo(state = initialState, action) {
switch (action.type) {
case CHANGE_MODE:
return { ...state, mode: action.mode };
case GENERATE_DATA:
return { ...state, data: createData() };
default:
return state;
}
}
const rootReducer = combineReducers({
demo,
});
export default rootReducer;
16. Component CSS
// SeriesBarChart.jsx
import classNames from 'classnames';
const styles = require('./SeriesBarChart.scss');
class SeriesBarChart extends Component {
render() {
return (
<svg className={classNames(styles.seriesbarchart)}
ref={svg => this.svg = svg}
width={this.props.width}
height={this.props.height}>
</svg>
);
}
}
18. Thanks! Questions?
We are hiring:
Python backend developers
web front-end developers
Follow @teemu on Twitter to stay in touch.
Email: teemu@ouraring.com