为啥这个子组件不重新渲染?

Posted

技术标签:

【中文标题】为啥这个子组件不重新渲染?【英文标题】:Why doesn't this child component rerender?为什么这个子组件不重新渲染? 【发布时间】:2017-07-12 15:25:55 【问题描述】:

我正在尝试使用 ReactJS,并试图了解如何触发子组件渲染。在 ReactJS 中,如果我设置这样的示例:

var externalCounterVar = 10
class Counter extends React.Component 
  constructor(props)
    super(props);
    this.state = props;
  
  render() 
    console.log('rendering counter')
    return (
       <div> externalCounterVar </div>
    )
  


class Main extends React.Component 
  constructor(props)
    super(props);
  
  handleClick() 
    externalCounterVar += 1;
  
  rerender()
    this.render();
  
  render() 
    console.log('rendering');
    return (
      <div>
        <button onClick=this.rerender.bind(this) />
        <Counter counter=externalCounterVar />
      </div>
    )
  


ReactDOM.render(<Main />, document.getElementById('root'));

我不确定我是否理解为什么当您“重新渲染”时它调用 Main 的渲染方法而不是 Counter?似乎它应该调用这两个渲染方法,因为它正在渲染 Main 并且 Counter 是 Main 的子级。

所以当调用 rerender 时,'rendering' 会打印,但 'rendering counter' 不会。

【问题讨论】:

【参考方案1】:

在这种情况下,您不必使用rerender 方法,也可以使用setState 方法重新渲染您需要更新状态的所有子组件。并且根据this,您必须“向上移动状态”。

这是我的例子:

class Counter extends React.Component 
    render() 
        console.log('rendering counter');
        return (<div> this.props.counter </div>);
    

class Main extends React.Component 
    constructor(props)
        super(props);
        this.state = counter: props.counter;
        this.handleClick = this.handleClick.bind(this);
    
    handleClick() 
        this.setState(prevState => (counter: ++prevState.counter));
    
    render() 
        console.log('rendering');
        return (
            <div>
                <button onClick=this.handleClick />
                <Counter counter=this.state.counter />
            </div>
        );
    

var externalCounterVar = 10;
ReactDOM.render(
    <Main counter=externalCounterVar />,
    document.getElementById('root')
);

【讨论】:

【参考方案2】:

在某些情况下,您可以使用this.forceUpdate() 调用重新渲染。 但是,如果你不能做到这一点,就不要这样做。 https://facebook.github.io/react/docs/react-component.html#forceupdate

【讨论】:

【参考方案3】:

您似乎忽略了使用 React 的主要好处之一,即状态的工作原理。

    您永远不需要在 React 组件中调用 this.render 你不应该动态设置状态,即:this.state = ... 您应该始终使用this.setState 来设置您的状态。

重写后,您的代码应如下所示:

const externalCounterVar = 10
class Counter extends React.Component 
  render() 
    console.log('rendering counter')
    return (
       <div> this.props.counter </div>
    )
  


class Main extends React.Component 
  state = 
    counter: externalCounterVar
  
  handleClick() 
    this.setState(counter: this.state.counter + 1);
  
  render() 
    console.log('rendering');
    return (
      <div>
        <button onClick=this.handleClick.bind(this) />
        <Counter counter=this.state.counter />
      </div>
    )
  

通过调用this.setState,React 自动知道它需要重新渲染你的组件,因此所有子组件也将被重新渲染。

希望这会有所帮助!

【讨论】:

我只是在搞乱 api,知道这是一个反模式。

以上是关于为啥这个子组件不重新渲染?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 vue 组件不重新渲染?

为啥 `useContext` 不重新渲染我的组件?

为啥组件在状态更改后不重新渲染。在 react-native 函数组件中

为啥在 React 中,当父组件重新渲染时子组件不会重新渲染(子组件没有被 React.memo 包裹)?

React:如何防止在`map`中重新渲染子组件?

为啥 useState 不触发重新渲染?