Using ReactHooks With D3
源码:https://github.com/muratkemaldar/using-react-hooks-with-d3
The Basics
在过去,我们必须依赖于 class component 和 life circle method 来进行D3的绘图。但是在React引入了hooks之后,我们的选择就不仅仅是class component了。我们可以利用 React 中的Hooks函数配合D3 来进行绘图。
首先我们来介绍我们需要用到的hooks
useState
https://zhuanlan.zhihu.com/p/92349623
useRef
https://blog.csdn.net/weixin_43720095/article/details/104966218
ref是React提供的用来操纵React组件实例或者DOM元素的接口。如果你将 ref
对象以 <div ref={myRef} />
形式传入组件,则无论该节点如何改变,React 都会将 ref
对象的 .current
属性设置为相应的 DOM 节点。
useRef
返回一个可变的 ref 对象,其 .current
属性被初始化为传入的参数(initialValue
)。返回的 ref 对象在组件的整个生命周期内保持不变。
本质上,useRef
就像是可以在其 .current 属性中保存一个可变值的“盒子”。
然而,useRef()
比 ref
属性更有用。它可以很方便地保存任何可变值,其类似于在 class 中使用实例字段的方式。
这是因为它创建的是一个普通 Javascript
对象。而 useRef
() 和自建一个 {current: …}
对象的唯一区别是,useRef
会在每次渲染时返回同一个 ref 对象。
useRef
有什么作用呢,其实很简单,总共有三种用法
- 作用于Dom元素
- 获取子组件的实例(只有类组件可用)
- 在函数组件中的一个全局变量,不会因为重复 render 重复申明, 类似于类组件的 this.xxx
useEffect
http://www.ptbird.cn/react-hoot-useEffect.html
https://zhuanlan.zhihu.com/p/84697185
Effect Hook 可以让你能够在 Function 组件中执行副作用(side effects):
1 | import { useState, useEffect } from 'react'; |
上面代码看过很多次了,是 React 文档中 Hook 部分一直使用的计数器示例,但是多了个新的功能:把文档标题设置为包含点击次数的自定义消息。而这就是一个副作用。
数据获取,设置订阅或者手动直接更改 React 组件中的 DOM 都属于副作用。有的人习惯成这种行为为 effects
,我是比较习惯叫 side effects
也就是副作用的, 这是个概念,需要在 React 必须习惯的概念。
如果熟悉 React 类声明周期方法,可以把 useEffect
Hook 视作 componentDidMount
、componentDidUpdate
和 componentWillUnmount
的组合体。
useEffect
的第二个参数可选 ,可用于定义其依赖的所有变量。如果其中一个变量发生变化,则useEffect会再次运行。如果包含变量的数组为空,则在更新组件时useEffect不会再执行,因为它不会监听任何变量的变更。。
使用useEffect
,不要调用函数层次太多,代码应该一眼看清楚哪些函数会被useEffect调用。
React+D3 with Hooks :
首先我们在一个function component当中引入 state,是一个数组
然后我们创建一个ref对象,这个对象是一个svg
在然后我们使用useEffect
Hooks也就是给这个svg
对象添加一些副作用,这个副作用就是渲染我们的图元。在useEffect
当中,我们把svgRef
中的current属性(就是一个svg
对象)抽象出来称为svg
,我么可以对这个svg添加属性,这样就可以渲染出来了。
两个按钮的原理: 点击 Update Data的话,利用setData
,把data中所有的值全部加上5. 点击Filter Data的时候,筛选出小于等于25的值,然后通过setData
更新data,因为更新过后的data和useEffect
中的data数组不一样,所以useEffect
会被重新调用,从而实现更新效果
1 | import React, { useRef, useEffect, useState } from "react"; |
Curved Line Chart
现在我们来画曲线图,我们需要d3库当中的 line
和 curveCardinal
(用来把折线变成曲线)
line: line方法用于绘制直线,只需要起始和结束点的x轴和y轴坐标就可以确定一段直线的位置。它会为我们的path生成d属性。d这个属性,包含一系列的方法与参数.因此我们可以把这个属性称作一个“微语言” ,这些方法与参数其实就是告诉电脑”如何在纸上移动你的钢笔”.
path: 可以渲染各种各样的图形,d3.line
可以帮助我们生成 d 属性用于描述折线。
那么对于myline这个图元,怎么确定他的横纵坐标呢?
对于横坐标,我们传入value和value的index,然后令横坐标就等于index*50 ,在svg画布上每个点的横坐标相当于:0,50,100,…这样的间隔 ;对于纵坐标,就随便我们定了;我们还加入了curve(curveCarginal)
目的就是让曲线变得光滑
我们在正式画图的时候,这里要了解 .data([data]) 的意思。这里我们打整个data数组放到另一个数组当中。这样,d3 就只会根据我们的data数组生成一条path,如果是.data(data)的话,d3会为数组当中的 每一个元素生成一条path,也就是仅仅是几个点罢了。 所以我们用 .data([data])的写法,
.attr("d", (value) => myline(value))
中,第二个参数是一个回调函数,value值接收我们整个data数组,也就是[[25, 30, 45, 60, 20,29,99]] 作为参数 因为这里只有一个子数组,那么就仅仅生成一条path。 然后我们把数据交给myline去处理,让他生成每一个点的横纵坐标。
1 | import React, { useRef, useEffect, useState } from "react"; |
Axes and Scales
1 | import React, { useRef, useEffect, useState } from "react"; |