mr-wellick / react-d3-ggplot Goto Github PK
View Code? Open in Web Editor NEWreact and d3 for data visualizations on the web
License: GNU General Public License v3.0
react and d3 for data visualizations on the web
License: GNU General Public License v3.0
Remove generic used in this interface. Removing the generic will simplify how you use the interface throughout the codebase.
/*
old code
*/
interface IAppContext<T> {
data: T[];
aes: [string, string];
dimensions: { width: number; height: number; padding: number };
}
const ChartContext = createContext<IAppContext<string | number | object>>({
data: [],
aes: ["", ""],
dimensions: { width: window.innerWidth, height: window.innerHeight, padding: 50 }
});
/*
after refactor
*/
interface IAppContext {
data: { [key: string]: object | string | number }[]
aes: [string, string];
dimensions?: { width: number; height: number; padding: number };
}
const ChartContext = createContext<IAppContext>({
data: [],
aes: ["", ""],
dimensions: { width: window.innerWidth, height: window.innerHeight, padding: 50 }
});
Allow user to change the color of the grid lines when using XGrid and YGrid as standalone units
These two components, XAxis
and YAxis
, have the same logic more or less. The same is true of the other components listed in the title of the issue.
The main difference is whether we use an x or y axis! Look into generalizing this structure throughout the listed components.
const XAxis = () => {
const ref = useRef(null);
const { aes, dimensions } = useContext(ChartContext);
// aes contains two values representing either the x or y values we want to visualize
const scale = useScale(aes[0]);
// need to set the range to properly display our graph visually
scale.range([dimensions.padding, dimensions.width - dimensions.padding]);
useEffect(() => {
const axisLocation = `translate(0, ${dimensions.height - dimensions.padding})`;
const node = select(ref.current).attr('transform', axisLocation);
node.call(axisBottom(scale));
}, [dimensions.height, dimensions.padding, scale]);
return <g ref={ref} />;
};
const YAxis = () => {
const ref = useRef(null);
const { aes, dimensions } = useContext(ChartContext);
// aes contains two values representing either the x or values we want to visualize
const scale = useScale(aes[1]);
// need to set the range to properly display our graph visually
scale.range([dimensions.height - dimensions.padding, dimensions.padding]);
useEffect(() => {
const axisLocation = `translate(${dimensions.padding}, 0)`;
const node = select(ref.current).attr('transform', axisLocation);
node.call(axisLeft(scale));
}, [dimensions.padding, scale]);
return <g ref={ref} />;
};
When we have no data to render, we need a placeholder chart that will adhere to the specified dimensions of the other charts that have been rendered to the DOM as we tab between different charts.
Instead of returning <h1>No Data</h1>, we can return a placeholder chart with a custom embedded message. This will make it so our content doesn't "jump" in height or width. Instead, we will maintain a consistent ui/ux.
// currently, these two hooks take no arguments
useXScale();
useYScale();
// consider adding a parameter in function definition to eliminate code and
// make it easier to maintain.
useScale("x")
useScale("y")
Add contributor guide for both experienced devs and beginners
Allow users to change the color of the background
// 1. Add type information to props
function XAxis(props) {
const context = useContext<IAppContext<string | number | object>>(ChartContext);
const scale: AxisScale<AxisDomain> = useScale(context, "XAxis");
useEffect(() => {
const { dimensions, aes, data } = context;
const axisLocation = `translate(0, ${dimensions.height - dimensions.padding})`;
// select node returned by component and appends x-axis
const node = select<SVGGElement, string | number | object>("g")
.attr("transform", axisLocation)
.call(axisBottom(scale));
if (typeof data[0][aes[0]] === "number" && props.label !== undefined) {
node.selectAll<SVGTextElement, number>("text").html(d => format(props.label)(d));
}
});
return <g />;
}
Link to file: https://github.com/Ll2NZ/react-d3-ggplot/blob/master/src/XAxis/XAxis.tsx
Create new branch documentation
for all future docs
Before refactoring any more React components, change the no-implicit-any from false
to true
and begin removing implicit any's
!
{
"compilerOptions": {
// Raise error on expressions and declarations with an implied 'any' type.
"noImplicitAny": false
}
}
Change optional prop name from color to fill just to stay consistent with all the other components in the library.
// Change from color to fill
interface IProps {
color?: string;
}
function Background(props: IProps) {
const { dimensions } = useContext(ChartContext);
return (
<rect
width={dimensions.width - dimensions.padding * 2}
height={dimensions.height - dimensions.padding * 2}
fill="#f1f1f1"
transform={`translate(${dimensions.padding}, ${dimensions.padding})`}
/>
);
}
FILE: https://github.com/Ll2NZ/react-d3-ggplot/blob/master/src/Background/Background.tsx
Sometimes we need to format our x or y values along the x or y axis.
interface IContext {
data: any[];
aes: string[];
dimensions?: { width: number; height: number; padding: number };
x_format?: string;
y_format?: string;
}
Take a step back and figure out how to clean and improve the current codebase
Specifying the dimensions of the graph should be handled internally. We can also make the chart responsive by default.
Check out this discussion: https://stackoverflow.com/questions/17626555/responsive-d3-chart
// current API
const LineChart = () => {
const [state, setState] = useState({
data: [{ x: 0, y: 0 }, { x: 10, y: 10 }],
aes: ["x", "y"],
dimensions: { width: 500, height: 300, padding: 50 }
});
return (
<GGPLOT {...state}>
<Line />
</GGPLOT>
);
};
// suggested API
const ScatterPlot = () => {
const [state, setState] = useState({
data: [{ x: 0, y: 0 }, { x: 10, y: 10 }],
aes: ["x", "y"]
});
return (
<GGPLOT {...state}>
<Points />
</GGPLOT>
);
};
This is next to the description ๐ค
Some are:
Best to be consistent
When used as standalone components we should not remove the x or y axis path. Add new prop to give this control to the user
For example Jest is used in React, just cover the happy paths even a single test per component will do.
Use a unique key other than index when rendering arrays into lists. The reason is that the index alone (so 0 to n, the length of the list) isn't "unique" enough to take full advantage of the optimization provided by React when using the key property for each item in the list.
When using rects, and one switches the X and Y values, the scales don't change accordingly and will result in errors
<g>
{context.data.map((datum, index) => (
<rect
key={index}
width={xScale.bandwidth()} // this works for ordinal scales but we need to account for time and number scales as well
height={yScale.range()[0] - yScale(datum[context.aes[1]])}
x={xScale(datum[context.aes[0]])}
y={yScale(datum[context.aes[1]])}
fill={!props.fill ? "cyan" : props.fill}
/>
))}
</g>
This will simplify code base
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.