npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

d3-react-component

v2.0.1

Published

A class-based React Componenet for D3 visualizations

Downloads

13

Readme

D3-React-Component logo

Coverage Status License: MIT build status dependency count: 0 minzipped size Gitlab npm package

D3-React-Component provides a React component wrapper for any d3 visualization. The component is called "D3Chart" and the entire package is only 1.9kb gzipped!(Seriously, this README is bigger than the entire build at ~8kb)

Design Philosophies

  • [x] Should provide a single class component which can be extended to work with any existing d3 code
  • [x] Should have a dead-simple API that contains only 3 methods: Create, Update, Destroy
  • [x] Should work with d3 loaded in a script tag, just like if you weren't using react. It must not require any other d3-related react libraries to work
  • [x] Zero dependency

Installation

NPM

npm install d3-react-component

Manual

  1. Copy D3Chart.js from the /src folder of this repository into the /src folder of your react app.
  2. profit

Usage

  1. Load d3 in a script tag. (add <script src="https://d3js.org/d3.v6.min.js"></script> to your index.html file)
  2. Create a class for your chart which extends the included D3Chart class component
  3. Write your chart initialization d3 code in your charts "create" method
  4. Write your chart update d3 code in your charts "update" method
  5. If you want to run custom d3 code before the component is unmounted from the dom, write this code in your charts "destroy" method.
  6. If you do not want to run custom d3 code before the component is unmounted from the dom, do not create a "destroy" method in your chart subclass. The parent class (D3Chart) will automagically take care of properly destroying the root svg element before the component is unmounted.

Notes:

- Class must have a create method
	- Use this method to store chart-specific functions, variables, etc
 - Class must have an update method
   	 - Use this method to render the chart, update scale domains, perform enter/exit/update etc
 - Class may have an optional destroy method
 	 - Use this method to run custom d3 code before the component is unmounted from the DOM
	 - If no destroy method is present in your subclass, the parent class will take care of destroying the root svg element for you

Reasons to extend the provided Chart class (It is highly recommended that you do so)

 - Margin math is done for you and is accessible from your subclass with `this.margin`
 - Default margins are setup for you (20px default)
 - A reference to the window.d3 object is mapped to `this.d3` for your subclass

Examples

Step1: Create a subclass for your chart (extend the provided D3Chart class):

The first step is to create a class for your chart/visualization. The class that you create is required to have 2 methods, with an optional third method. Each of these methods directly maps to a phase in Reacts DOM lifecycle.

  • Create: This method is called after the canvas node has been mounted to the DOM
    • Use it to create the SVG element on the page, create your scales, and init any other d3 functions
  • Update: This method is called any time a new data prop is passed to your charts subclass
    • Use it to render your chart, perform enter/update/exit transitions, update your scale domains, etc
  • Destroy (optional method): This method is called before React unmounts the canvas node from the DOM
    • Use it if you need to clean up after yourself.

Here is a very basic example of what it looks like when you extend the provided D3Chart class. We'll call our chart "MyAwesomeChart" and we'll save it in its own file

"MyAwesomeChart.js"


import {D3Chart} from "d3-react-component" // If you used NPM
//import D3Chart from "./D3Chart.js" // If you performed a manual install

export default class MyAwesomeChart extends D3Chart {
	/**
	 * Create and store the necessary functions for your vis
	 * @param canvasNode - The DOM node that will contain your vis. Append your svg element to this!
	 * @param data - The data that was initially passed to the vis
	 * @param props - any properties that you passed to your subclass. (Except margins, we'll discuss that later...)
	 */
	create( canvasNode, data, props ){
		// Create the SVG element
		this.svg = this.d3.select( canvasNode ) // Access the d3 object with this.d3
		  .append( "svg" )
			.attr( "width", this.totalWidth ) // this.totalWidth provided by D3Chart parent class
			.attr( "height", this.totalHeight ) // this.totalHeight provided by D3Chart parent class
		  .append( "g" )
			.attr(
				"transform",
				`translate( ${this.margin.left},${this.margin.top} )` // This.margin object provided by Chart.js
			);
		// This is where you create and store your scales, axis formats, path generators, etc
	}

	/**
	 * Anytime your subclass component is updated with new data, this
	 * function is called. use it to update/transition your vis
	 * @param data - The new data
	 */
	update( data ){
		// Code to update the chart
		// This is where you update your scale domains, perform enter/exit/update etc
	}
}
  • Notice that we don't need any margin logic. Our parent class takes care of that for us by following the conventions laid out here
  • Notice that you automagically get a reference to the d3 object. Use this.d3. ( again, the parent class takes care of this for us )
  • If you chose not to extend the provided Chart class, you will have to get a reference to the d3 object yourself (typically just window.d3). You will also have to perform any margin mathematics yourself. see here

Step 2: Render your chart component

Next, you need to simply render your chart as you would any other react component

"App.js"

	import MyAwesomeChart from "./MyAwesomeChart.js"

	const data = // Retrive your data however you want. Whether that be a static svg, database query, etc
	function App(){
		return(
			<MyAwesomeChart
				id={"some_unique_id"}
				data={data}
				width={1000}
				height={500}
				leftMargin={50}
				rightMargin={20}
				topMargin={35}
				bottomMargin={20}
			/>
		);
	}
  • Note: All margins default to 0px, but we have overridden them here. These override will take effect even though your subclass does not implement any margin logic. This is take care of automatically by the D3Chart parent class
  • Note: Both width and height default to 500px. Again, the D3Chart parent class allows this to happen without you having to write any logic for it in your subclass.

Custom properties

any custom properties that you pass to your subclass component will be passed to the create method as the third parameter ( props )

App.js

	import MyAwesomeChart from "./MyAwesomeChart.js"
	function App(){
		return(
			<MyAwesomeChart
				id={"some_unique_id"}
				...
				myCustomProperty={{
					foo: "bar"
				}}
			/>
		 );
	}

MyAwesomeChart.js

import {Chart} from "d3-react-component"
export default class MyAwesomeChart extends Chart {

	create( canvasNode, data, props ){
		console.log( props )
		// Outputs { myCustomProperty : { foo: "bar" } }
		...
	}

	update( data ){...}
}

Accessing Margins, Width, and Height

Margins

You can access the margins in your chart class with this.margin. For instance, if you want to get the left margin, just use this.margin.left.

Width and Height ( minus margins )

You can access the computed width and height with this.wdith and this.height respectively. ( these values are minus margins )

Total Width and Total Height ( width and height including margins )

If you would like to access the total width or total height you can use this.totalWidth and this.totalHeight respectively. ( these values include the margins )

Refactoring An existing chart

If you have existing D3 charts, they can be quite easily refactored into a subclass of D3Chart. I have adapted this chart to a Chart class so that you can compare them. (You will find it along with its data file in the "examples" folder of the repository)

To run the example:

  1. Start by placing data.csv into the /public folder
  2. Next, Place D3Chart.js and LineChart.js in the /src folder
  3. Edit App.js as to look as follows
import React from 'react';
import './App.css';
import {D3Chart} from "d3-react-component"
import LineChart from "./LineChart.js"
function App() {
	return (
		<LineChart
			id={"LineChart"}
			data={"data.csv"}
			leftMargin={50}
			width={1000}
			height={500}
		  />
	);
}

export default App;