简体   繁体   English

React加快了嵌套组件的渲染速度

[英]React speed up rendering of nested components

I'm trying to implement a syntax highlighter using React. 我正在尝试使用React来实现语法荧光笔。 The syntax highligher component itself is Redux independent, but Redux is still relevant. 语法highligher组件本身是Redux独立的,但是Redux仍然是相关的。

The highlighter takes 2 props 荧光笔需要2个道具

structure - It's a 2d array with the id's of tokens to be rendered, split to lines, example: structure -这是一个二维数组,其中包含要渲染的令牌ID,分为几行,例如:

const structure = [
  [ // a line
    "ryMtafN9b",
    "r1WftTfEcZ",
    "rkfftaMV5W"
  ],
  [ // another line
    "B1sGYTG4cZ",
    "By3MYpzEq-"
  ],
  ...
]

tokens - A mapping between token id and token, example: tokens -令牌ID和令牌之间的映射,例如:

const tokens = {
  "ryMtafN9b": {
    "type": "LEFT_SQUARE_BRACKET",
    "value": "[",
    "id": "ryMtafN9b"
  },
  "r1WftTfEcZ": {
    "type": "WHITESPACE",
    "value": "  ",
    "id": "r1WftTfEcZ"
  },
  "rkfftaMV5W": {
    "type": "LEFT_CURLY_BRACKET",
    "value": "{",
    "id": "rkfftaMV5W"
  },
  ...
}

The rendering then happens like this (removed all irrelevant stuff): 然后,渲染就这样进行(删除了所有不相关的内容):

One token 一个令牌

class TokenElement extends PureComponent {
  render() {
    // return a <span> based on the token type, etc
  }
}

One row (line) 一行(行)

class TokenRow extends PureComponent {
  render() {
    const { tokens } = this.props
    return (<div>
      {tokens.map((token) => <TokenElement token={token} key={token.id} />)}
    </div>)
  }
}

The actual highlighter component 实际的荧光笔组件

class JsonSyntaxHighlighter extends PureComponent {
  render() {
    const { tokens, structure } = this.props
    return (<pre>
      {
        structure.map((line) => (<TokenRow tokens={line.map((tokenId) => tokens[tokenId])} />))
      }
    </pre>)
  }
}

The problem The reason I'm implementing a custom syntax highlighter, is because I need to add custom decorations on token level based on data coming in async. 问题之所以我实现自定义语法荧光笔,是因为我需要基于异步传入的数据在令牌级别添加自定义修饰。 These updates coming in the form of extending each token in the tokens object, without mutations through a reducer (The whole highlighter component is rendered by a connected smart component). 这些更新以扩展tokens对象中的每个令牌的形式出现,而没有通过reducer进行更改(整个荧光笔组件由连接的智能组件呈现)。 Even though all the components are PureComponent s the re-rendering of one single token takes a long time since: 即使所有组件都是PureComponent ,单个令牌的重新渲染也需要很长时间,因为:

  1. JsonSyntaxHighlighter checks if needs to update - YES (since the tokens object changed in it's props) JsonSyntaxHighlighter检查是否需要更新- (因为tokens对象在道具中已更改)
  2. TokenRow checks if needs to update - YES (since it's tokens array has changed, because it's a result of a map ping) TokenRow检查是否需要更新- (因为它的tokens数组已更改,因为它是map ping的结果)
  3. TokenElement checks if needs to update MAYBE (since now I can rely on shouldComponentUpdate properly). TokenElement检查是否需要更新MAYBE (因为现在我可以正确地依赖shouldComponentUpdate )。

Now when a lot's of these small updates arrive in a relatively small interval, the UI just blocks since a tons of re-renders are queued up. 现在,当许多这样的小更新以相对较小的间隔到达时,由于大量的重新提交排队,因此UI只是阻塞了。

Question Can I structure my data or my components better, so that frequent changes in individual token's state can trigger renders fast, without checking the whole tree? 问题我可以更好地构造数据或组件的结构,以便频繁地更改单个令牌的状态而无需检查整个树就可以快速触发渲染吗?

Facebook has a great article on exactly this topic. Facebook在这个主题上有一篇很棒的文章。

Short answer is to use React's shouldComponentUpdate lifecycle method generously to specify when whole the component tree should avoid updating. 简短的答案是慷慨地使用React的shouldComponentUpdate生命周期方法来指定整个组件树何时应避免更新。 Here are a few examples on how to do that. 以下是一些有关如何执行此操作的示例。

I don't have proper code samples (it would be too much code to post here) but the way I ended up solving this is batching the plentiful store updates into chunks using Observable s ( rxjs , buffer operator). 我没有合适的代码示例(在此处发布太多代码),但最终解决此问题的方法是使用Observable s( rxjsbuffer运算符)将大量存储更新分批处理。 This made the reducer code a bit more complex since state merges were not so natural, but now I have complete control over how frequently the store updates happen, and this implies control over how frequently render s happen. 由于状态合并不是很自然的,这使化简代码变得更加复杂,但是现在我可以完全控制商店更新的发生频率,这意味着可以控制render频率。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM