cheslijones
cheslijones

Reputation: 9194

Modifying element in React component after it has rendered

This is part of a parent component that gets some px measurements between elements after the child component has rendered:

componentDidMount() {

    // get the element where print area resides
    let iframe = document.getElementById('ifmcontentstoprint').contentWindow.document.body;

    // get the list of elements
    let printArea = iframe.querySelectorAll('#printarea');
    let positionTitle = iframe.querySelectorAll('#printarea .position-title, .position-title-print');
    let pageFooter = iframe.querySelectorAll('#printarea tr.footer');          

    // total number of pages
    var i = positionTitle.length;

    // the position of the printarea within the the element
    let printAreaPos = printArea[0].getBoundingClientRect().top

    // iterate through the elements that are pairs
    for (let i = 0; i <= positionTitle.length - 1; i++) {
         console.log(pageFooter[i].getBoundingClientRect().top - positionTitle[i].getBoundingClientRect().top);
        pageFooter[i].style.marginTop = '50px';
    }
}

Where the pageFooter[i].style.marginTop = '50px'; is that will eventually be programmatically set. Just working with static a number for now for testing purposes.

This is part of the child component where the style is supposed to be added:

<tr className='footer'>
    <td id='hide'>
        <div>
            <div align='left' className='footer-columns'>
                <p className='effective-date'>DATE EFFECTIVE: {this.props.effectiveDate}</p>
                <p>&copy; THE COMPANY</p>
                <p>UNAUTHORIZED REPRODUCTION OR DISTRIBUTION PROHIBITED</p>
            </div>
            <div align='center' className='footer-columns middle-column'>
                <p>{this.props.surveyName}</p>
                <p>Page {i === 2 ? 1 : i === 5 ? 2 : i === this.props.totalCuts ? this.props.maxPages : null} of {this.props.maxPages}</p>
            </div>
            <div align='right' className='footer-columns'><img src={logo} alt='The Company Logo' /></div>
        </div>
    </td>
</tr>

I wasn't seeing why pageFooter[i].style.marginTop = '50px'; wasn't being reflected, but when I changed the <tr className='footer' style={{ marginTop: '50px' }}> it did work even though it looked like it was rendering the same HTML.

So I finally figured out the modifications being done in the componentDidMount() where not getting added back to the DOM--they were just hanging out in memory basically.

How should I get this sent back to the DOM?

I eventually want to be able to do pageFooter - positionTitle position comparisons which requires the child component to render first to get the measurement.

Upvotes: 1

Views: 872

Answers (2)

rsalmeidafl
rsalmeidafl

Reputation: 411

At a first glance I can't figure out why what you coded doesn't work. I'm simply going to provide another way to look at this, which is by letting React control the marginTop of the elements itself. To do that, we must use the component's state to store the desired margins, and then use {{ marginTop: measurement }} as you indicated. Here is a possible outline of such approach:

class YourComponent extends React.Component {

    constructor(props) {
        super(props);
        this.state = { margins: [] };
    }

    componentDidMount() {
        // same as your previous code ...
        const newMargins = [];

        for (let i = 0; i <= positionTitle.length - 1; i++) {
            newMargins.push('50px');
        }

         this.setState({ margins: newMargins });
    }

    render() {
        const { margins } = this.state;

        // and finally, you somehow make margins[index] reach your
        // child component (the exact implementation depends on how
        // your component is structured)
        <tr className="footer" style={{ marginTop: margins[myIndex] }} />
    }
}

Upvotes: 1

Tiago Alves
Tiago Alves

Reputation: 2316

The style property is used to style DOM elements not any variable or array.

So, when you are doing this: pageFooter[i].style.marginTop = '50px'; you are not targeting the DOM element but a element in the array. To accomplish this you can do: iframe.querySelectorAll('#printarea tr.footer')[i].style.marginTop = '50px' instead.

Upvotes: 0

Related Questions