Реакция компонентов повторного рендеринга из-за нескольких стилей - PullRequest
0 голосов
/ 14 января 2019

Я сталкиваюсь с проблемой рендеринга, когда передаю несколько стилей, например:

<StyledComponent style={[styles.styleOne, styles.styleTwo]} />

Если компонент StyledComponent содержится в повторных визуализациях, StyledComponent также выполнит повторную визуализацию, даже если реквизиты не изменятся.

Мне известно, что если родительский компонент вызывает setState, то его дочерние элементы будут повторно визуализироваться независимо от того, действительно ли изменяются собственные реквизиты дочерних элементов. Я пытался использовать PureComponent и React.memo. Тем не менее, мои дочерние компоненты все еще перерисовываются. Кажется, проблема в том, как я отправляю стили. Если я передам один стиль так:

<StyledComponent style={styles.styleOne} />

PureComponent / React.memo работает. Однако, если мой компонент имеет такой стиль:

<StyledComponent style={[styles.styleOne, styles.styleTwo]} />

тогда он каждый раз рендерится.

Это потому, что я создаю новый массив для каждого рендера родительского компонента, и PureComponent / React.memo не может определить, что это те же стили.

Итак, мой вопрос: как я могу использовать несколько стилей для компонента, не прибегая к написанию пользовательского shouldComponentUpdate для каждого из моих дочерних компонентов? Рендеринг заметно замедляет производительность моего приложения, так как я работаю со старыми устройствами Android, поэтому я хотел бы свести к минимуму необходимый рендеринг.

Вот закуска, демонстрирующая это: https://snack.expo.io/@tnortman/styles-r-stupid

Ответы [ 2 ]

0 голосов
/ 14 января 2019

Переместите массив стилей в переменную экземпляра класса и передайте ссылку через реквизит. Таким образом, это не новый массив для каждого рендера.

0 голосов
/ 14 января 2019

Если вы не хотите реализовывать пользовательский mustComponentUpdate, вам нужно убедиться, что массив прошел проверку ===. Есть несколько возможностей для этого, в зависимости от того, как или если это может измениться. Если он никогда не изменится, то это самое простое: просто создайте массив один раз, а затем ссылайтесь на него. Например:

const styles = StyleSheet.Create({
  styleOne: {
    backgroundColor: 'red',
  },
  styleTwo: {
    padding: 40,
  },
});

// Note that this line is not in render
const combined = [styles.styleOne, styles.styleTwo];

// ...

// in render:

<StyledPureComponent style={combined} />

Если это возможно изменить, вам нужно добавить код для управления этим. Скорее всего, я создал бы запомненную функцию, которая производит массив и пересчитывает только то, что изменилось. Например, вот пример, который иногда включает в себя style2, а иногда нет, на основе реквизита:

// Just an example; you could use a different library or implement it yourself
import memoize from "memoize-one";

const combineStyles = memoize((shouldIncludeStyleTwo) => {
  const styles = [styles.styleOne];
  if (shouldIncludeStyleTwo) {
     styles.push(styles.styleTwo);
  }
  return styles;
});

// ...

<StyledPureComponent style={combineStyles(this.props.something)} />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...