我有一些嵌套的React组件,其内部是一个大svg
图,其中包含数百个line
和rect
个元素。为了启用某些应用程序范围的行为和外观更改,我想更改最上面组件的className
。问题是,如果我这样做,整个应用程序会重新呈现。
我理解这种行为在单向渲染流的意义上是有意的,但我认为React会更聪明地重用它并将DOM更改保持在最低限度。
此处的最小示例:https://jsbin.com/rabofewawu/1/edit?html,js,output 如您所见,每次按“此处”时SVG中的线条图案都会发生变化,但我只想更改背景颜色。
当我尝试通过更改内部svg
元素的transform
属性来缩放和平移g
时,会出现类似但更极端的示例。使用d3,我只需更改属性。使用react,我的render
函数被调用,更新后的状态会生成更新的transform
属性,整个组将从头开始重新渲染,而不是更改DOM属性。
我错过了什么吗?什么是React方式来实现我想要做的事情?
答案 0 :(得分:2)
您可以使用组件的shouldComponentUpdate
功能来控制它。默认情况下,它始终返回true(因此组件将始终重新呈现)。
这里有一些关于此功能的文档https://facebook.github.io/react/docs/component-specs.html#updating-shouldcomponentupdate
答案 1 :(得分:2)
采用这种简单无害的渲染功能:
render(){
return <div>{Date.now()}</div>;
}
在React的心智模型中,这将始终显示每毫秒的当前数字。 React概念上每秒更新无限次。渲染的输入在这里是世界上的一切,但我们碰巧只是使用时钟。给定相同的世界,我们从渲染中获得相同的输出,因此它是幂等的。
好的废话......我们没有无限快速的计算机,所以我们需要妥协。而不是渲染的输入是我们将其限制为状态和道具(和上下文)的所有内容。在此限制设置中,使用Math.random或Date.now会破坏规则。如果你需要使用这些的输出,它必须首先通过状态或道具。这看起来怎么样?那么我们可以使用确定性随机数生成器并将种子存储在状态中。这是modified version of your component做到这一点:
var MyComponent = React.createClass({
displayName:"MyComponent",
getInitialState(){
return {
seed: Math.floor(Math.random()*0xffffff)
};
},
render: function() {
// make a random number generator with the given seed
var rng = new Chance(this.state.seed);
function random(x){
return rng.floating({min: 0, max: x, fixed: 7})
}
var s=100, lines = [];
for (var i=0; i<100; i++) {
var line = { x1: random(s), y1: random(s), x2: random(s), y2: random(s) };
lines.push(React.createElement("line", line));
}
return React.createElement("svg", { height: s, width: s}, lines);
}
});
每秒渲染少于无限次,并且仅渲染某些组件是一种优化。优化不应该影响程序的行为。
如果您想要不同的随机数,可以将种子设置为不同的随机数。在这里使用真实Math.random()
是可以的,因为状态是代码中的结果或i / o操作,并且您在响应其他一些i / o(例如点击处理程序)时调用此setState。
时间相似;如果要渲染当前时间,请使用setTimeout和setState以及当前时间。然后,您可以在渲染中显示它的喜好,包括将其传递给其他组件并对其进行任何类型的数学运算。