简体   繁体   中英

React doesn’t rerender component if already rendered once

I have a component called ChildComponent which I call from ParentComponent as below. Point to be noted:

  1. There is a button "Show Child".
  2. On the first Click of this button it should do a fresh rerender of the child component. But on Subsequent clicks, it should not even Call ChildComponent but instead fetch the dom from this.refs. For this I am using return this.refs.chid which gives error

Below is the code.

ParentComponent= React.creatClass({
  getInitialState: function(){
    return {
      rendered: false
    }
  },
  render_or_cache: function(){
    if (this.state.rendered){
      return this.refs.child;
    }
    else {
      return <ChildComponent/>
    }
  },
  onbuttonclick: function(){
    this.setState({rendered: true})
  },
  render:function(){
    return (
      <div ref="child">
        {this.render_or_cache()}
      </div>
      <button onClick={this.onbuttonclick()}>Show Child Again</button>
    )
  }
})

ChildComponent= React.creatClass({
  render:function(){
    return (
      <div>Some Text from Child</div>
    )
  }
})

You have to store your component inside state

Try out this

Code:

ParentComponent= React.creatClass({
getInitialState: function(){
   return {
             childComponent :[]
          }
},

onbuttonclick: function(){
   this.setState({childComponent.concat(<ChildComponent/>)})
}
render:function(){

return (
      <div ref="child">
           {this.state.childComponent}
     </div>
     <button onClick={this.onbuttonclick()}>Show Child Again</button>
)}
})

ChildComponent= React.creatClass({
render:function(){

return (
        <div>Some Text from Child</div>
)}
})

You have some inconsistencies in your term usage.

Mounting is when a component didn't use to exist, and then exists. Mounting starts from initial state and includes a render.

Rerendering happens when the properties/state of a component change, but the component hierarchy does not change. This preserves the component state.

I'm not sure how you're trying to accomplish what you say by returning this.refs.child . A simple way to accomplish a single-time effect like this is to simply conditionally render the element, like so:

render:function(){
const child = (this.state.rendered) ? <ChildComponent/> : ""

return (
      <div>
           {child}
     </div>
     <button onClick={this.onbuttonclick()}>Show Child Again</button>
)}
})

Do note that in this approach, changing rendered from true to false will cause ChildComponent to unmount, losing the state of that component instance. I imagine in most cases this would be wanted behavior.

When to Use Refs

There are a few good use cases for refs:

Managing focus, text selection, or media playback. Triggering imperative animations. Integrating with third-party DOM libraries. Avoid using refs for anything that can be done declaratively.

For example, instead of exposing open() and close() methods on a Dialog component, pass an isOpen prop to it.

https://facebook.github.io/react/docs/refs-and-the-dom.html

For your purpose you can use conditional rendering by checking your state and deciding which component you should render. https://facebook.github.io/react/docs/conditional-rendering.html

Hope it helps.

It seems to me that you're jumping hoops to achieve something that React already does really well; determine when to re-render your component and when to update the DOM.

If you know better than React when to re-render a component, you can define a shouldComponentUpdate(nextProps, nextState) method on your component that takes the next props and state of your component and returns true or false based on your own rules.

See the lifecycle methods in the React documentation: https://facebook.github.io/react/docs/react-component.html#shouldcomponentupdate

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM