首页 文章

React:更新子组件而不重新渲染父组件

提问于
浏览
2

以下是一个简单的例子:

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的链接:

https://codepen.io/mytee306/pen/yxezEy

每秒使用当前时间更新Clock时调用this.setState({date:new Date()}) . 据我所知,setState调用App上的render方法,导致整个组件被重新呈现,包括Label .

有没有办法将日期传递给Clock(导致它被重新渲染)而不重新渲染整个App组件?这在性能方面发挥了多大的作用?

1 回答

  • 2

    你想要的不可能 . 要将prop传递给子组件,父组件的状态或道具应该以某种方式改变 . 如你所知,这显然会触发重新渲染,因此所有的孩子都会重新渲染 . 要进行更新,应在此情况下重新呈现和卸载/重新安装 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>
        )
      }
    
    }
    

相关问题