Реагируйте: Обновите дочерний компонент без перерисовки родительского компонента - PullRequest
0 голосов
/ 25 августа 2018

Ниже приведен простой пример:

const { Component } = React
const { render } = ReactDOM

const Label = ({text}) => (<p>{text}</p>)

const Clock = ({ date }) => (
  <div>{date.toLocaleTimeString()}</div>
)

class App extends Component {
  
  constructor() {
    super()
    this.state = {
      date: new Date()
    }
  }
  
  componentWillMount() {
    this.interval = setInterval(
      () => this.setState({ date: new Date() }),
      1000
    )
  }
  
  componentWillUnmount() {
    clearInterval(this.interval)
  }
  
  updateTime() {
    
  }
  
  render() {
    return (
      <div>
        <Label text="The current time is:" />
        <Clock date={this.state.date} />
      </div>
    )
  }
  
}

render(<App />, document.querySelector('#app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="app"></div>

Вот ссылка на codepen

this.setState({ date: new Date() }) вызывается каждую секунду, обновляя часы текущим временем. Насколько мне известно, setState вызывает метод рендеринга в приложении, который вызывает перерисовку всего компонента, включая метку.

Есть ли способ передать дату в Clock (вызывая ее повторную визуализацию) без перерисовки всей компоненты приложения? Насколько большую роль это играет в отношении производительности?

1 Ответ

0 голосов
/ 25 августа 2018

Это не возможно, что вы хотите. Чтобы передать реквизит дочернему компоненту, состояние или реквизиты родительского компонента должны как-то измениться. Как вы знаете, это вызывает повторную визуализацию, поэтому все дочерние элементы выполняют повторную визуализацию. Для обновления ваш Clock компонент должен быть повторно обработан и размонтирован / перемонтирован в этой ситуации, чтобы отразить изменение DOM.

Если ваше приложение не такое большое и у него не так много детей, не боритесь с этой проблемой, поскольку рендеринг не такой дорогой. Дорогое - это манипулирование DOM-компонентом. Здесь React использует реальный и виртуальный DOM и не размонтирует / перемонтирует компонент Label, даже если он будет перерисован. Но, если вы напишите свой Label компонент как PureComponent, он не будет перерисован. Но для Clock компонента, который будет обновлен подобным образом, нет никакого способа.

class Label extends React.PureComponent {
  render() {
    console.log("rendered");
    return (<p>{this.props.text}</p>)
  }
}

const Clock = ({ date }) => (
  <div>{date.toLocaleTimeString()}</div>
)

class App extends React.Component {

  constructor() {
    super()
    this.state = {
      date: new Date()
    }
  }


  componentWillMount() {
    this.interval = setInterval(
      () => this.setState({ date: new Date() }),
      1000
    )
  }

  componentWillUnmount() {
    clearInterval(this.interval)
  }

  updateTime() {

  }

  render() {
    return (
      <div>
        <Label text="The current time is:" />
        <Clock date={this.state.date} />
      </div>
    )
  }

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