Controlling Order of React Component Rendering

PositiveGuy

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:

  1. InterviewContentMain (because it will render the header

    . 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)

  2. InterviewContainer (should only render after InterviewContentMain has rendered)
  3. TableOfContents (should only render after InterviewContainer and InterviewContentMain have rendered)

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>
        )
    }
})
azium

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>
    )
}

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

change component rendering order

From Dev

React: is there a better pattern for higher-order component rendering?

From Dev

React: is there a better pattern for higher-order component rendering?

From Dev

Simple React component not rendering

From Java

Dynamically Rendering a React component

From Dev

React router not rendering component

From Dev

React router not rendering component

From Dev

Rendering a Component Instance in React

From Dev

React not rendering component

From Dev

Basic react component not rendering

From Dev

Rendering Math in React Component

From Dev

React - server side component rendering

From Dev

React - server side component rendering

From Dev

Component rendering with React in Rails not working

From Dev

Method in React component not rendering HTML

From Dev

Rendering react component in html page

From Dev

React Router component rendering twice

From Dev

Rendering a dynamic child component in React

From Dev

React: Rendering the component in different way

From Dev

React component not rendering on route changed

From Dev

React component not rendering on with latest version

From Dev

React: Rendering a list in reverse order

From Dev

React Parent Component Not Rendering Child Component

From Dev

Dynamically Rendering a React Component in React 0.12

From Dev

Controlling order of execution in angularjs

From Dev

Controlling Order of Callbacks with Tkinter

From Dev

Decorate imported React component with higher order component

From Dev

React router dynamic routes not rendering component

From Dev

React component not re-rendering on state change