forked from kay-is/react-from-zero
-
Notifications
You must be signed in to change notification settings - Fork 13
/
16-advanced-integration.html
137 lines (107 loc) · 4.13 KB
/
16-advanced-integration.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
<!doctype html>
<title>16 Integração Avançada - React do Zero</title>
<script src="https://unpkg.com/react@16.4.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.4.0/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/create-react-class@15.6.3/create-react-class.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script src="https://unpkg.com/d3@4.7.3/build/d3.min.js">
// Algumas vezes devemos integrar libraries mais
// complexas. Libraries que querem usar o
// DOM diretamente ou requerem interações assíncronas.
// Neste exemplo usamos D3.js, uma library de Visualização de Dados gratuita
</script>
<div id="app"></div>
<script type="text/babel">
// Já que o D3 precisa interagir diretamente com o DOM nós
// devemos usar uma classe componente, porque ela pode guardar
// referências para seus elementos-DOM.
var Visual = createReactClass({
// Simplesmente renderizamos um canvas vazio e dizemos para o React
// guardar sua referência após a renderização.
render: function() {
return <canvas ref={this.handleRef} width={500} height={500}/>
},
handleRef: function(canvas) {
this.canvas = canvas
},
// Após a primeira renderização, pegamos a referência
// para o elemento canvas no DOM e passamos a referência
// para a library
componentDidMount: function() {
// Aqui usamos uma configuração de cor adicional
drawGraph(this.canvas, this.props.color)
},
// Também temos um controle fino e granular sobre as re-renderizações
// com o uso deste método de ciclo de vida
shouldComponentUpdate: function(nextProps, nextState) {
// Aqui podemos passar para a library os novos dados de propriedades
// ou estado, para que ele possa atualizar os elementos DOM por conta própria.
// No fim sempre retornamos falso para que o nosso método renderizador
// não seja chamado e o elemento canvas não seja substituido
return false
},
// Esse método do ciclo de vida pode ser usado para liberar recursos
// antes que o componente seja removido do DOM.
// Nosso canvas será removido com certeza, mas normalmente existe
// um estado da library, outros objetos, listeners etc.
// eles podem ser guardados no componente e devem ser
// deletados para prevenir leaks de memória
componentWillUnmount() {},
})
// Agora podemos usar a library como um componente
// Sem a necessidade de IDs globais, cada instância tem seu próprio canvas
// por referênciamento, e suas proprias propriedades de cor.
var reactElement =
<div>
<Visual color="#f00"/>
<Visual color="#0f0"/>
<Visual color="#00f"/>
</div>
ReactDOM.render(reactElement, document.getElementById("app"))
// Encapsulando a interação da library em uma função
function drawGraph(canvas, strokeColor) {
// Um exemplo de http://bl.ocks.org/mbostock/1b64ec067fcfc51e7471d944f51f1611
// licensiado sob a GPL-V3
var n = 20
var nodes = d3.range(n * n).map(function(i) {
return {index: i}
})
var links = []
for (var y = 0; y < n; ++y) {
for (var x = 0; x < n; ++x) {
if (y > 0) links.push({source: (y - 1) * n + x, target: y * n + x});
if (x > 0) links.push({source: y * n + (x - 1), target: y * n + x});
}
}
d3.forceSimulation(nodes)
.force("charge", d3.forceManyBody().strength(-30))
.force("link", d3.forceLink(links).distance(20).iterations(10))
.on("tick", ticked)
var context = canvas.getContext("2d")
var width = canvas.width
var height = canvas.height
function ticked() {
context.clearRect(0, 0, width, height)
context.save()
context.translate(width / 2, height / 2)
context.beginPath()
links.forEach(drawLink)
context.strokeStyle = "#aaa"
context.stroke()
context.beginPath()
nodes.forEach(drawNode)
context.fill()
context.strokeStyle = strokeColor
context.stroke()
context.restore()
}
function drawLink(d) {
context.moveTo(d.source.x, d.source.y)
context.lineTo(d.target.x, d.target.y)
}
function drawNode(d) {
context.moveTo(d.x + 3, d.y);
context.arc(d.x, d.y, 3, 0, 2 * Math.PI)
}
}
</script>