diff --git a/packages/showcase/examples/force-directed-graph/force-directed-example.js b/packages/showcase/examples/force-directed-graph/force-directed-example.js
index 7048044b2..386a0a410 100644
--- a/packages/showcase/examples/force-directed-graph/force-directed-example.js
+++ b/packages/showcase/examples/force-directed-graph/force-directed-example.js
@@ -18,36 +18,30 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-import React from 'react';
+import React, {useState} from 'react';
import LesMisData from './les-mis-data.json';
import './force-directed.scss';
import ForceDirectedGraph from './force-directed-graph';
-export default class ForceDirectedExample extends React.Component {
- state = {
- strength: Math.random() * 60 - 30
- };
-
- render() {
- const {strength} = this.state;
- return (
-
- this.setState({strength: Math.random() * 60 - 30})}
- >
- {' '}
- REWEIGHT{' '}
-
-
-
- );
- }
+const makeStrength = () => Math.random() * 60 - 30;
+export default function ForceDirectedExample() {
+ const [strength, setStrength] = useState(makeStrength);
+ return (
+
+ setStrength(makeStrength())}
+ >
+ REWEIGHT
+
+
+
+ );
}
diff --git a/packages/showcase/examples/force-directed-graph/force-directed-graph.js b/packages/showcase/examples/force-directed-graph/force-directed-graph.js
index 779357de0..ce7c5403d 100644
--- a/packages/showcase/examples/force-directed-graph/force-directed-graph.js
+++ b/packages/showcase/examples/force-directed-graph/force-directed-graph.js
@@ -18,8 +18,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-import React from 'react';
-import PropTypes from 'prop-types';
+import React, {useState, useEffect} from 'react';
import {forceSimulation, forceLink, forceManyBody, forceCenter} from 'd3-force';
import {XYPlot, MarkSeriesCanvas, LineSeriesCanvas} from 'react-vis';
@@ -44,7 +43,6 @@ const colors = [
/**
* Create the list of nodes to render.
* @returns {Array} Array of nodes.
- * @private
*/
function generateSimulation(props) {
const {data, height, width, maxSteps, strength} = props;
@@ -54,7 +52,7 @@ function generateSimulation(props) {
// copy the data
const nodes = data.nodes.map(d => ({...d}));
const links = data.links.map(d => ({...d}));
- // build the simuatation
+ // build the simulation
const simulation = forceSimulation(nodes)
.force(
'link',
@@ -76,71 +74,51 @@ function generateSimulation(props) {
return {nodes, links};
}
-class ForceDirectedGraph extends React.Component {
- static get defaultProps() {
- return {
- className: '',
- data: {nodes: [], links: []},
- maxSteps: 50
- };
- }
-
- static get propTypes() {
- return {
- className: PropTypes.string,
- data: PropTypes.object.isRequired,
- height: PropTypes.number.isRequired,
- width: PropTypes.number.isRequired,
- steps: PropTypes.number
- };
- }
+export default function ForceDirectedGraph(props) {
+ const {
+ className = '',
+ height,
+ width,
+ animation,
+ data = {
+ nodes: [],
+ links: []
+ },
+ maxSteps = 50,
+ strength
+ } = props;
+ const [{nodes, links}, setData] = useState({
+ nodes: [],
+ links: []
+ });
+ useEffect(() => {
+ setData(generateSimulation({data, height, width, maxSteps, strength}));
+ }, [data, height, width, maxSteps, strength]);
- constructor(props) {
- super(props);
- this.state = {
- data: generateSimulation(props)
- };
- }
-
- UNSAFE_componentWillReceiveProps(nextProps) {
- this.setState({
- data: generateSimulation(nextProps)
- });
- }
-
- render() {
- const {className, height, width, animation} = this.props;
- const {data} = this.state;
- const {nodes, links} = data;
- return (
-
- {links.map(({source, target}, index) => {
- return (
-
- );
- })}
-
-
- );
- }
+ return (
+
+ {links.map(({source, target}, index) => {
+ return (
+
+ );
+ })}
+
+
+ );
}
-
-ForceDirectedGraph.displayName = 'ForceDirectedGraph';
-
-export default ForceDirectedGraph;
diff --git a/packages/showcase/examples/responsive-vis/responsive-bar-chart.js b/packages/showcase/examples/responsive-vis/responsive-bar-chart.js
index d9bed0823..8d5b18c19 100644
--- a/packages/showcase/examples/responsive-vis/responsive-bar-chart.js
+++ b/packages/showcase/examples/responsive-vis/responsive-bar-chart.js
@@ -48,59 +48,56 @@ function updateDataForArea(data, ppp) {
return sample;
}
-export default class ResponsiveBarChart extends React.Component {
- // todo build a root responsive class that has this as a class method
- getFeatures() {
- const {data, height, margin, width} = this.props;
- const innerWidth = width - margin.left - margin.right;
- const innerHeight = height - margin.top - margin.bottom;
- const ppp = getPPP(innerWidth, innerHeight, data, 'HEIGHT');
- return filterFeatures(BARCHART_FEATURES, ppp);
- }
+export function getFeatures(props) {
+ const {data, height, margin, width} = props;
+ const innerWidth = width - margin.left - margin.right;
+ const innerHeight = height - margin.top - margin.bottom;
+ const ppp = getPPP(innerWidth, innerHeight, data, 'HEIGHT');
+ return filterFeatures(BARCHART_FEATURES, ppp);
+}
- render() {
- const {data, height, margin, width} = this.props;
+export default function ResponsiveBarChart(props) {
+ const {data, height, margin, width} = props;
- const innerWidth = width - margin.left - margin.right;
- const innerHeight = height - margin.top - margin.bottom;
- const ppp = getPPP(innerWidth, innerHeight, data, 'HEIGHT');
- const featuresToRender = filterFeatures(BARCHART_FEATURES, ppp);
- const updatedData = featuresToRender.area
- ? updateDataForArea(data, ppp)
- : data;
+ const innerWidth = width - margin.left - margin.right;
+ const innerHeight = height - margin.top - margin.bottom;
+ const ppp = getPPP(innerWidth, innerHeight, data, 'HEIGHT');
+ const featuresToRender = filterFeatures(BARCHART_FEATURES, ppp);
+ const updatedData = featuresToRender.area
+ ? updateDataForArea(data, ppp)
+ : data;
- return (
-
-
- {featuresToRender.xaxis && }
- {featuresToRender.yaxis && }
- {featuresToRender.bars && (
-
- )}
- {featuresToRender.area && (
-
- )}
-
-
- );
- }
+ return (
+
+
+ {featuresToRender.xaxis && }
+ {featuresToRender.yaxis && }
+ {featuresToRender.bars && (
+
+ )}
+ {featuresToRender.area && (
+
+ )}
+
+
+ );
}
diff --git a/packages/showcase/examples/responsive-vis/responsive-scatterplot.js b/packages/showcase/examples/responsive-vis/responsive-scatterplot.js
index ac3b0f449..39f778fa6 100644
--- a/packages/showcase/examples/responsive-vis/responsive-scatterplot.js
+++ b/packages/showcase/examples/responsive-vis/responsive-scatterplot.js
@@ -18,7 +18,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-import React from 'react';
+import React, {useState, useEffect} from 'react';
import {
XYPlot,
MarkSeries,
@@ -67,38 +67,29 @@ export const SCATTERPLOT_FEATURES = [
}
];
-export default class ResponsiveScatterplot extends React.Component {
- state = {
- binData: [],
- hoveredPoint: false,
- selectedPoints: []
- };
-
- UNSAFE_componentWillReceiveProps(nextProps) {
- // not the greatest
- this.setState({
- binData: transformToBinData(
- nextProps.data,
- nextProps.width,
- nextProps.height
- )
- });
- }
-
- getFeatures() {
- const {data, height, margin, width} = this.props;
- const innerWidth = width - margin.left - margin.right;
- const innerHeight = height - margin.top - margin.bottom;
- const ppp = getPPP(innerWidth, innerHeight, data, 'HEIGHT');
- return filterFeatures(SCATTERPLOT_FEATURES, ppp);
- }
+export function getFeatures(props) {
+ const {data, height, margin, width} = props;
+ const innerWidth = width - margin.left - margin.right;
+ const innerHeight = height - margin.top - margin.bottom;
+ const ppp = getPPP(innerWidth, innerHeight, data, 'HEIGHT');
+ return filterFeatures(SCATTERPLOT_FEATURES, ppp);
+}
- _select(accessor) {
+export default function ResponsiveScatterplot(props) {
+ const {data, height, margin, width} = props;
+ const [binData, setBinData] = useState([]);
+ const [hoveredPoint, setHoveredPoint] = useState(false);
+ const [selectedPoints, setSelectedPoints] = useState([]);
+ useEffect(() => {
+ setBinData(transformToBinData(data, width, height));
+ }, [data, width, height]);
+ // const {binData, hoveredPoint, selectedPoints} = this.state;
+ function select(accessor) {
return (value, e) => {
e.event.stopPropagation();
let foundValue = false;
- const selectedPoints = this.state.selectedPoints.filter(row => {
+ const updatedSelectedPoints = selectedPoints.filter(row => {
if (accessor(row) === accessor(value)) {
foundValue = true;
}
@@ -106,86 +97,70 @@ export default class ResponsiveScatterplot extends React.Component {
});
if (!foundValue) {
- selectedPoints.push(value);
+ updatedSelectedPoints.push(value);
}
-
- this.setState({selectedPoints});
+ setSelectedPoints(updatedSelectedPoints);
};
}
- render() {
- const {binData, hoveredPoint, selectedPoints} = this.state;
- const {data, height, margin, width} = this.props;
- const innerWidth = width - margin.left - margin.right;
- const innerHeight = height - margin.top - margin.bottom;
+ const innerWidth = width - margin.left - margin.right;
+ const innerHeight = height - margin.top - margin.bottom;
- const ppp = getPPP(innerWidth, innerHeight, data, 'TWOD');
- const featuresToRender = filterFeatures(SCATTERPLOT_FEATURES, ppp);
- const rememberVal =
- featuresToRender.pointSelection || featuresToRender.tooltips;
- const rememberBin =
- featuresToRender.bintips || featuresToRender.binSelection;
+ const ppp = getPPP(innerWidth, innerHeight, data, 'TWOD');
+ const featuresToRender = filterFeatures(SCATTERPLOT_FEATURES, ppp);
+ const rememberVal =
+ featuresToRender.pointSelection || featuresToRender.tooltips;
+ const rememberBin = featuresToRender.bintips || featuresToRender.binSelection;
- const pointRadii = computeRadius(data, innerWidth, innerHeight);
+ const pointRadii = computeRadius(data, innerWidth, innerHeight);
- const showHint =
- (featuresToRender.tooltips || featuresToRender.bintips) && hoveredPoint;
- return (
-
-
- {featuresToRender.axes && }
- {featuresToRender.axes && }
- {featuresToRender.bins && (
- this.setState({hoveredPoint: value})
- : null
- }
- onValueMouseOut={
- rememberBin ? () => this.setState({hoveredPoint: null}) : null
- }
- onValueClick={
- featuresToRender.binSelection
- ? this._select(d => `${d.x}-${d.y}`)
- : null
- }
- data={manicureData(binData, hoveredPoint, selectedPoints, true)}
- />
- )}
- {featuresToRender.points && (
- this.setState({hoveredPoint: value})
- : null
- }
- onValueMouseOut={
- rememberVal ? () => this.setState({hoveredPoint: null}) : null
- }
- onValueClick={
- featuresToRender.pointSelection
- ? this._select(d => d.label)
- : null
- }
- data={manicureData(data, hoveredPoint, selectedPoints, false)}
- />
- )}
- {showHint && }
- {featuresToRender.labels && (
-
- )}
-
-
- );
- }
+ const showHint =
+ (featuresToRender.tooltips || featuresToRender.bintips) && hoveredPoint;
+ return (
+
+
+ {featuresToRender.axes && }
+ {featuresToRender.axes && }
+ {featuresToRender.bins && (
+ setHoveredPoint(value) : null
+ }
+ onValueMouseOut={rememberBin ? () => setHoveredPoint(null) : null}
+ onValueClick={
+ featuresToRender.binSelection
+ ? select(d => `${d.x}-${d.y}`)
+ : null
+ }
+ data={manicureData(binData, hoveredPoint, selectedPoints, true)}
+ />
+ )}
+ {featuresToRender.points && (
+ setHoveredPoint(value) : null
+ }
+ onValueMouseOut={rememberVal ? () => setHoveredPoint(null) : null}
+ onValueClick={
+ featuresToRender.pointSelection ? select(d => d.label) : null
+ }
+ data={manicureData(data, hoveredPoint, selectedPoints, false)}
+ />
+ )}
+ {showHint && }
+ {featuresToRender.labels && (
+
+ )}
+
+
+ );
}
diff --git a/packages/showcase/examples/responsive-vis/responsive-vis-example.js b/packages/showcase/examples/responsive-vis/responsive-vis-example.js
index 72fda453f..8ec21a5af 100644
--- a/packages/showcase/examples/responsive-vis/responsive-vis-example.js
+++ b/packages/showcase/examples/responsive-vis/responsive-vis-example.js
@@ -18,11 +18,15 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-import React from 'react';
+import React, {useState} from 'react';
import {createData, getPPP} from './responsive-vis-utils';
-import ResponsiveScatterplot from './responsive-scatterplot';
-import ResponsiveBarChart from './responsive-bar-chart';
+import ResponsiveScatterplot, {
+ getFeatures as getScatterplotFeatures
+} from './responsive-scatterplot';
+import ResponsiveBarChart, {
+ getFeatures as getBarFeatures
+} from './responsive-bar-chart';
import 'styles/examples.scss';
import './responsive-vis.scss';
@@ -30,105 +34,92 @@ import './responsive-vis.scss';
const ASPECT_RATIO = 1.2;
const EXAMPLE_MARGIN = {left: 60, top: 60, bottom: 50, right: 50};
-export default class ResponsiveVisDemo extends React.Component {
- state = {
- dataSize: 1,
- visSize: 400,
- data: createData(5, true),
- chartType: 'barChart'
- };
+export default function ResponsiveVisDemo() {
+ const [chartType, setChartType] = useState('barChart');
+ const [data, setData] = useState(() => createData(5, true));
+ const [visSize, setVisSize] = useState(400);
+ const [dataSize, setDataSize] = useState(1);
+
+ const ResponsiveChartType =
+ chartType === 'barChart' ? ResponsiveBarChart : ResponsiveScatterplot;
- handleTypeClick(chartType) {
- const {dataSize} = this.state;
- return () => {
- this.setState({
- chartType,
- data: createData(~~Math.pow(10, dataSize), chartType === 'barChart')
- });
- };
- }
+ const handleTypeClick = chartType => () => {
+ setChartType(chartType);
+ setData(createData(~~Math.pow(10, dataSize), chartType === 'barChart'));
+ };
- renderControls() {
- const {chartType, data, dataSize, visSize} = this.state;
- const width = visSize;
- const height = visSize * ASPECT_RATIO;
- const ppp = getPPP(width, height, data, 'TWOD');
- const featuresToRender =
- (this.responsiveExample && this.responsiveExample.getFeatures()) || {};
+ const width = visSize;
+ const height = visSize * ASPECT_RATIO;
+ const ppp = getPPP(width, height, data, 'TWOD');
+ const featuresProps = {width, height, data, margin: EXAMPLE_MARGIN};
+ const featuresToRender = (chartType === 'barChart'
+ ? getBarFeatures
+ : getScatterplotFeatures)(featuresProps);
- return (
-
-
{`Points Per Pixel: ${ppp}`}
-
- {`Features: ${Object.keys(featuresToRender).join(', ')}`}
-
-
-
- Scatterplot
+ return (
+
+
+
+
{`Points Per Pixel: ${ppp}`}
+
+ {`Features: ${Object.keys(featuresToRender).join(', ')}`}
-
- BarChart
+
+
+ Scatterplot
+
+
+ BarChart
+
-
- {`Data Size: ${~~Math.pow(10, dataSize)}`}
-
{
- this.setState({
- dataSize: e.target.value,
- data: createData(
- ~~Math.pow(10, e.target.value),
- this.state.chartType === 'barChart'
- )
- });
- }}
- type="range"
- min={1}
- max={6}
- step={0.1}
- value={dataSize}
- />
-
- {`Visualization size: ${visSize}`}
-
this.setState({visSize: ~~e.target.value})}
- type="range"
- min={100}
- max={1000}
- value={visSize}
- />
-
- );
- }
+ {`Data Size: ${~~Math.pow(10, dataSize)}`}
+
{
+ setDataSize(e.target.value);
+ setData(
+ createData(
+ ~~Math.pow(10, e.target.value),
+ chartType === 'barChart'
+ )
+ );
+ }}
+ type="range"
+ min={1}
+ max={6}
+ step={0.1}
+ value={dataSize}
+ />
- render() {
- const {chartType, data, visSize} = this.state;
- const ResponsiveChartType =
- chartType === 'barChart' ? ResponsiveBarChart : ResponsiveScatterplot;
- return (
-
-
{this.renderControls()}
-
(this.responsiveExample = ref)}
- margin={EXAMPLE_MARGIN}
- height={ASPECT_RATIO * visSize}
- width={visSize}
- />
+ {`Visualization size: ${visSize}`}
+ setVisSize(~~e.target.value)}
+ type="range"
+ min={100}
+ max={1000}
+ value={visSize}
+ />
+
- );
- }
+
+
+ );
}
diff --git a/packages/showcase/sunbursts/clock-example.js b/packages/showcase/sunbursts/clock-example.js
index 0666bcc97..41eb4cf1a 100644
--- a/packages/showcase/sunbursts/clock-example.js
+++ b/packages/showcase/sunbursts/clock-example.js
@@ -18,7 +18,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-import React from 'react';
+import React, {useState, useEffect} from 'react';
import {XYPlot, ArcSeries} from 'react-vis';
@@ -30,53 +30,42 @@ function getSeconds() {
return Math.floor(new Date().getTime() / 1000);
}
-export default class ClockExample extends React.Component {
- state = {
- time: 0
- };
-
- componentDidMount() {
- this._timerId = setInterval(() => this.setState({time: getSeconds()}), 100);
- }
-
- componentWillUnmount() {
- clearInterval(this._timerId);
- this.setState({timerId: false});
- }
-
- render() {
- const {time} = this.state;
- const seconds = time % 60;
- const minutes = (time / 60) % 60;
- const hours = (time / (60 * 24)) % 24;
- return (
-
d.time}
- getAngle0={() => 0}
- height={300}
- >
-
-
- );
- }
+export default function ClockExample() {
+ const [time, setTime] = useState(getSeconds());
+ useEffect(() => {
+ const handle = setInterval(() => setTime(getSeconds()), 100);
+ return () => clearInterval(handle);
+ }, []);
+ const seconds = time % 60;
+ const minutes = (time / 60) % 60;
+ const hours = (time / (60 * 24)) % 24;
+ return (
+
d.time}
+ getAngle0={() => 0}
+ height={300}
+ >
+
+
+ );
}