As you know React components render in parallel. There is no guarantee in order that they finish rendering.
I want to render the following components in this exact order:
. I need this header to render first so that I can act on it in my other two components after rendered. I am going to run some JS on it, etc. later on from those other two component's componentDidMount so that's why I want this to render first)
Here is a little more context https://youtu.be/OrEq5X9O4bw
I tried a bunch of stuff as you can see with the lifecycle methods, which is probably totally wrong or not even sure it's what people are even doing for this sort of scenario, but no luck so far.
const Main = Component({
getInitialState() {
console.log("getInitialState being called");
return null;
},
renderMe() {
console.log("changed InterviewContent's state");
this.setState({renderInk: true});
},
componentDidMount() {
console.log("InterviewContentMain mounted");
},
render(){
var company = this.props.company;
return (
<div id="ft-interview-content">
<p className="section-heading bold font-22" id="interview-heading">Interview</p>
<InterviewContent renderMe={this.renderMe} company={company}/>
</div>
)
}
})
export default InterviewContentMain;
const InterviewContent = Component({
componentDidMount() {
console.log("InterviewContent mounted");
},
renderMe() {
console.log("changed InterviewContent's state");
this.setState({subParentRendered: true});
},
render(){
var company = this.props.company;
return (
<div id="interview-content" className="clear-both">
<div className="column-group">
<div className="all-20">
<TableOfContents renderHeader={this.props.renderMe} renderContent={this.renderMe} company={company}/>
</div>
<div className="all-80">
<InterviewContainer company={company}/>
</div>
</div>
</div>
)
}
})
const TableOfContents = Component({
enableInk() {
new Ink.UI.Sticky(el, {topElement: "#interview-heading", bottomElement: "#footer"});
},
componentDidMount() {
console.log("table of contents mounted");
this.renderHeader;
this.renderContent;
enableInk(); // I only want to run this if the Header and the Content have rendered first
},
render(){
return (
<div>
<p className="margin-8"><span className="blue medium"><Link to="/">HOME</Link></span></p>
)
}
})
UPDATE:
here's what I tried. While they all 3 render, I'm still getting times where TableOfContents renders before InterviewContentMain or InterviewContent which means TableOfContent after rendered overlaps <p className="section-heading bold font-22" id="interview-heading">Interview</p>
instead of rendering underneath it due to the sticky JS I tried to apply in TableOfContents
const InterviewContentMain = Component({
getInitialState() {
console.log("getInitialState being called");
return {rendered: false};
},
componentDidMount() {
console.log("InterviewContentMain mounted")
this.setState({rendered: true});
},
render(){
var company = this.props.company;
return (
<div id="ft-interview-content">
<div className="section-heading bold font-22" id="interview-heading">Interview</div>
{ this.state.rendered && <InterviewContent company={company}/> }
</div>
)
}
})
export default InterviewContentMain;
const InterviewContent = Component({
getInitialState() {
console.log("getInitialState being called");
return {rendered: false};
},
componentDidMount() {
console.log("InterviewContent mounted")
this.setState({rendered: true});
},
render(){
var company = this.props.company;
return (
<div id="interview-content" className="clear-both">
<div className="column-group">
<div className="all-20">
<TableOfContents company={company}/>
</div>
<div className="all-80">
<InterviewContainer company={company}/>
</div>
</div>
</div>
)
}
})
const TableOfContents = Component({
componentDidMount() {
const el = ReactDOM.findDOMNode(this);
new Ink.UI.Sticky(el,{topElement: "#interview-heading", bottomElement: "#footer"});
console.log("TableOfContents mounted");
},
render(){
return (
<div>
<p className="margin-8"><span className="blue medium"><Link to="/">HOME</Link></span></p>
</div>
)
}
})
componentDidMount. The componentDidMount() method is called after the component is rendered. This is where you run statements that requires that the component is already placed in the DOM.
useEffect order But in which order are they called? No surprises here. Everything outside the effects will run first, and then the effects will be called in order. Notice that useEffect accepts a dependency array, which will trigger the effect when the component first mounts and when any of the dependencies change.
componentDidMount() is only called once, on the client, compared to componentWillMount() which is called twice, once to the server and once on the client. It is called after the initial render when the client received data from the server and before the data is displayed in the browser.
If you want to conditionally render a component, wrap it in a conditional (whether a function or an inline boolean expression)
You say:
TableOfContents (should only render after InterviewContainer and InterviewContentMain have rendered)
.. so inside the render
method of TableOfContents
parent container, check whether some values are true, like you would in an if
statement.
render(){
var company = this.props.company;
return (
<div id="interview-content" className="clear-both">
<div className="column-group">
<div className="all-20">
{this.state.subParentRendered &&
<TableOfContents renderHeader={this.props.renderMe} renderContent={this.renderMe} company={company}/>
}
</div>
<div className="all-80">
<InterviewContainer company={company}/>
</div>
</div>
</div>
)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With