Created
January 5, 2022 01:14
-
-
Save cjgunnar/851cf2b10e735d1108451313a3eb2613 to your computer and use it in GitHub Desktop.
A basic, size-responsive, interactive React plot created with the excellent Plotly library
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Plotly from 'plotly.js-cartesian-dist'; | |
import { useEffect, useMemo, useState } from 'react'; | |
import createPlotlyComponent from 'react-plotly.js/factory'; | |
// use only portion of plotly library necessary | |
const Plot = createPlotlyComponent(Plotly); | |
/** | |
* a simple plot with x and y axis, will completely fill div it's placed in | |
* @param {Object} props | |
* @param {Array<Array<number>>} props.data pass in as [xseries, yseries] | |
* @param {string} props.xLabel label on x axis | |
* @param {string} props.yLabel label on y axis | |
* @param {boolean} props.log plot as a loglog plot | |
* @requires plotly.js-cartesian-dist | |
* @requires react-plotly.js | |
*/ | |
export function Chart({data, xLabel, yLabel, log=false}) { | |
// create data field | |
const graphData = useMemo(() => [{ | |
x: data[0], | |
y: data[1], | |
type: 'scatter', | |
mode: 'lines' | |
}], [data]); | |
// set layout parameters | |
const layout = useMemo(() => ({ | |
xaxis: { | |
title: xLabel ?? '', | |
rangemode: 'tozero', | |
type: log ? 'log' : 'linear' | |
}, | |
yaxis: { | |
title: yLabel ?? '', | |
rangemode: 'tozero', | |
type: log ? 'log' : 'linear' | |
}, | |
autosize: true | |
}), [xLabel, yLabel, log]); | |
// create persistent state across redraws | |
const [plotState, setPlotState] = useState({ | |
layout, | |
data: graphData, | |
config: { | |
responsive: true | |
}, | |
frames: [] | |
}); | |
useEffect(()=>{ | |
// merge old and new state | |
setPlotState(prev => ({...prev, data: graphData, layout})) | |
}, [graphData, layout]); | |
return ( | |
<div style={{boxSizing: 'border-box'}}> | |
<Plot | |
data={plotState.data} | |
layout={plotState.layout} | |
config={plotState.config} | |
frames={plotState.frames} | |
useResizeHandler | |
style={{width: '100%', height: '100%', boxSizing: 'border-box'}} | |
onInitialized={setPlotState} | |
onUpdate={setPlotState} | |
/> | |
</div> | |
); | |
} |
Wow didn't know people were finding this. Word of warning: I'm finding bugs relating to this code. I'll post a revision when that gets sorted out. Until then, check out this excellent blog post that does it properly.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@cjgunnar This looks promising, can you share a codepen link that demonstrates how to use this
Chart
component?