Skip to main content

React way to use D3 - ( Python as API )

The Inspiration
Andmap is trying to build new BI product, the tech stacks would be D3 + ReactJS as data visualization frontend, Web API, and Python provides data. As with most new projects, it didn’t take long to figure out the major roadblocks.
D3.js is a JavaScript library for manipulating documents based on data. D3 helps you bring data to life using HTML, SVG, and CSS. D3’s emphasis on web standards gives you the full capabilities of modern browsers without tying yourself to a proprietary framework, combining powerful visualization components and a data-driven approach to DOM manipulation.
In one of our initial discovery sessions, we realized that our application needs to be able to adapt D3 library in ReactJS way. More than that, we prefer utilizing new feature of React - Hooks. Finally, we build  component for each chart and Helpers file for drawing each chart.
Here is sample for map chart:


index.js:
<Map data={mapData} tooltipHtml={tooltipHtml} w={w} h={600} />




<Ball data={ballData} w={w} h={h / 4} />
<Bar data={barData} w={w} h={400} />
map.js - map chart container -
using useEffect hook
import React, { useEffect } from 'react'
import { drawMap } from './helpers.js'
import './map.css'
const Map = props => {
useEffect(() => {
drawMap(props)
}, [props.data.length])
return (
<>
<h2>US Map</h2>
<div className='map' />
<div id='tooltip'></div>
</>
)
}
export default Map
view raw map.js hosted with ❤ by GitHub

helpers.js
- to draw charts

How to trigger mouse event in React
const mouseOver = d => {
d3.select('#tooltip')
.transition()
.duration(200)
.style('opacity', 0.9)
d3.select('#tooltip')
.html(tooltipHtml(d.n, data[d.id]))
.style('left', d3.event.pageX + 'px')
.style('top', d3.event.pageY - 28 + 'px')
}
const mouseOut = () => {
d3.select('#tooltip')
.transition()
.duration(500)
.style('opacity', 0)
}
view raw helpers.js hosted with ❤ by GitHub
svgContainer
.selectAll('path')
.data(usStatePaths)
.enter()
.append('path')
.attr('class', 'state')
.attr('d', function (d) {
return d.d
})
.style('fill', function (d) {
return data[d.id].color
})
.on('mouseover', mouseOver)
.on('mouseout', mouseOut)
}
view raw helpers.js hosted with ❤ by GitHub


Conclusion

I hope this little tutorial is helpful to anyone who wants to take advantage of the D3 library inside of a React app. If I didn’t explain something well, or if something is wrong with my code, please leave a comment.

Comments

Popular posts from this blog

for loop in javascript - promise - .eslintrc for "for of"

the vast majority of cases  map ,  forEach ,  find  etc. can be used.  async function printFiles () { const files = await getFilePaths(); await Promise.all(files. map (async (file) => { const contents = await fs.readFile(file, 'utf8') console.log(contents) })); } const inventory = [ { name : 'apples' , quantity : 2 } , { name : 'bananas' , quantity : 0 } , { name : 'cherries' , quantity : 5 } ] ; const result = inventory . find ( ( { name } ) => name === 'cherries' ) ;   function getFirstMatching(array) { for (let item of array) { const result = heavyTransform(item); if (result) { return result; } } } Specifically this shuts down the whole no-restricted-syntax. If you want to cherry-pick, here is the current definition: 'no-restricted-syntax' : [ 'error' , { selector : 'ForInStatement' , message...

Apollo client - cache APIs - auto update cache - erase cache - reactive variables - deletion - addition

Apollo Client 3  Local only fields Reactive Variables const cache = new InMemoryCache ( { typePolicies : { Todo : { // If one of the keyFields is an object with fields of its own, you can // include those nested keyFields by using a nested array of strings: keyFields : [ "date" , "user" , [ "email" ] ] , } } , } ) ; This internal data is intended to be easily  JSON-serializable , so you can take a snapshot with  cache.extract() , save it somewhere, and later restore with  cache.restore(snapshot) . Here’s a mutation called  EditTodo  that returns the new  todo  value in the mutation response. mutation EditTodo ( $id : Int ! , $text : String ! ) { editTodo ( id : $id , text : $text ) { success todo { # <- Returning it here id text completed } error { ... on TodoNotFoundError { message } ... on TodoValidationE...

window.URL.createObjectURL is not (yet) available in jest-dom - testing scenario

Since  window.URL.createObjectURL  is not (yet) available in jest-dom, you need to provide a mock implementation for it. Don't forget to reset the mock implementation after each test. describe ( "your test suite" , () => { window . URL . createObjectURL = jest . fn (); afterEach (() => { window . URL . createObjectURL . mockReset (); }); it ( "your test case" , () => { expect ( true ). toBeTruthy (); }); });