Предоставление источника реактивных данных - PullRequest
1 голос
/ 12 апреля 2020

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

Вопросы: * Используется ли техника, в которой я использую звук? * Как предотвратить повторную визуализацию компонента, когда его входные данные не изменились?

Подробности: Я создал прототип «голыми руками» (см. Ниже). При этом используется экземпляр Source (который в самом приложении будет обновляться через коллекцию MongoDB) для предоставления реактивных данных для компонента представления. В моем прототипе я просто генерирую случайные данные.

У меня было два сюрприза.

Первый: я обнаружил, что если я вызываю .get() на ReactiveVar в источнике, этого достаточно для вызвать объект Tracker для чтения новых значений , даже если я верну значение полностью нереактивной переменной . Как и следовало ожидать, если значение ReactiveVar не изменяется, то Tracker игнорирует любые изменения нереактивной переменной.

Two: Полученное Tracker значение пересылается компоненту s props` вызывает повторную визуализацию , даже если значение не изменилось .

Код:

import React, { Component } from 'react'
import { ReactiveVar } from 'meteor/reactive-var'
import { withTracker } from 'meteor/react-meteor-data'


/// SOURCE ——————————————————————————————————————————————————————————

class Source {
  constructor() {
    this.updateData = this.updateData.bind(this)
    this.updateData()
  }

  updateData() {
    const reactive = Math.floor(Math.random() * 1.25) // 4 times as many 0s as 1s
    data.set(reactive)
    console.log("reactive:", reactive)

    this.usable = ["a", "b", "c"][Math.floor(Math.random() * 3)]
    console.log("usable:  ", this.usable)

    setTimeout(this.updateData, 1000)
  }

  get() {       
    data.get() // We MUST get a reactive value to trigger Tracker...
    return this.usable // ... but we CAN return a non-reactive value
  }
}


let data = new ReactiveVar(0)
const source = new Source()


/// COMPONENT ———————————————————————————————————————————————————————

class Test extends Component{

  render() {
    console.log("rendered:", this.props.data)

    return (
      <div>
        {this.props.data}
      </div>
    )
  }
}

export default withTracker(() => {
  const data = source.get()
  console.log("UPDATE:  ", data)
  console.log("")

  const props = {
    data
  }

  return props
})(Test)

Пример вывода консоли, с аннотациями:

reactive: 1
usable:   b
UPDATE:   b

rendered: b <<< initial value rendered
reactive: 1 <<< no change to reactive value...
usable:   a <<< ...so usable value is ignored
reactive: 0 <<< reactive value changes...
usable:   c <<< ... so an update is sent to the component
UPDATE:   c

rendered: c <<< c rendered
reactive: 0 <<< no change to the reactive value...
usable:   c
reactive: 0
usable:   b
reactive: 0
usable:   c
reactive: 0
usable:   b
reactive: 1 <<< but when reactive value changes
usable:   c <<< the usable value does not
UPDATE:   c

rendered: c <<< c re-rendered, although unchanged

Подводя итог: Мой план состоит в том, чтобы увеличивать ReactiveVar в моем экземпляре Source каждый раз, когда от студента поступает новая информация. Тем не менее, если студент просто перемещает курсор, то я хочу, чтобы только компонент, который отображает курсор студента, перерисовывал, а не весь вид. элегантно.

1 Ответ

0 голосов
/ 13 апреля 2020

Поведение, которое вы наблюдаете, является частью Метеора «волхвов» c - он видит, что ваша реактивная переменная зависит от простой переменной, и делает эту реактивную тоже слишком активной, или, что более правильно, он настраивает часы на нее.

withTracker часто запускает несколько рендеров, поэтому лучший способ оптимизировать это - использовать React.memo ()

. Мне лично не нравится React.memo, он кажется неуклюжим и делает разработчик делает работу, которая кажется ненужной. Здесь есть хорошая статья, которая объясняет это:

https://dmitripavlutin.com/use-react-memo-wisely/

Когда компонент упакован в React.memo (), React отображает его и запоминает результат. До следующего рендеринга, если новые реквизиты те же, React повторно использует запомненный результат, пропуская следующий рендеринг.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...