7

Please do not mark as duplicate. It is similar to other questions, but different, because I'm asking where to put the code, not how to write.

I have this code, and want to detect which section is in view:

export default class Home extends React.Component {
    render() {
        return (
            <React.Fragment>
                <div className="col_first">
                    <Scrollspy id="menu_section"
                               items={['section_1', 'section_2', 'section_3', 'section_4', 'section_5']}
                               currentClassName="is-current" className="c_nav_menu" style={{marginTop: 100}}>
                        <li className="c_nav_menu_item"><a href="#section_1">1</a></li>
                        <li className="c_nav_menu_item"><a href="#section_2">2</a></li>
                        <li className="c_nav_menu_item"><a href="#section_3">3</a></li>
                        <li className="c_nav_menu_item"><a href="#section_4">4</a></li>
                        <li className="c_nav_menu_item"><a href="#section_5">5</a></li>
                    </Scrollspy>

                    <div>
                        <li className="lines_between_1"></li>
                        <li className="lines_between_2"></li>
                        <li className="lines_between_3"></li>
                        <li className="lines_between_4"></li>
                    </div>
                </div>
                <section className="row bg_double">
                    <div className="col-lg-1">
                    </div>
                    <div className="col-lg-11  s_anim">
                        <div className="full_screen" id="section_1">
                            <div className="row full_size">
                                <div className="col-lg-12 center_in_s1">
                                    <h1 className="text_s1 gradient_text">ZdajTo</h1>
                                    <p>korepetycje on-line</p>
                                </div>
                            </div>
                            <div className="icon_border_round">
                                <a href="#section_2"><img src={"/assets/images/ic_arrow_down_gradient.png"}/></a>
                            </div>
                        </div>

                        <div className="full_screen" id="section_2">
                            <div className="row full_size">
                                <div className="col-lg-6 center_in">
                                    <h1> elo elo 320 </h1>
                                </div>
                                <div className="col-lg-6 center_in">
                                    <h1>Przykładowy tekst</h1>
                                </div>
                            </div>
                            <div className="icon_border_round">
                                <a href="#section_3"><img src={"/assets/images/ic_arrow_down_gradient.png"}/></a>
                            </div>
                        </div>

                        <div className="full_screen" id="section_3">
                            <div className="row full_size">
                                <div className="col-lg-6 center_in">
                                    <h1> elo elo 320 </h1>
                                </div>
                                <div className="col-lg-6 center_in">
                                    <h1>Przykładowy tekst</h1>
                                </div>
                            </div>
                            <div className="icon_border_round">
                                <a href="#section_4"><img src={"/assets/images/ic_arrow_down_gradient.png"}/></a>
                            </div>
                        </div>

                        <div className="full_screen" id="section_4">
                            <div className="row full_size">
                                <div className="col-lg-6 center_in">
                                    <h1> elo elo 320 </h1>
                                </div>
                                <div className="col-lg-6 center_in">
                                    <h1>Przykładowy tekst</h1>
                                </div>
                            </div>

                            <div className="icon_border_round">
                                <a href="#section_5"><img src={"/assets/images/ic_arrow_down_gradient.png"}/></a>
                            </div>

                        </div>


                        <div className="full_screen" id="section_5">
                            <div className="row full_size">
                                <div className="col-lg-6 center_in">
                                    <h1> elo elo 320 </h1>
                                </div>
                                <div className="col-lg-6 center_in">
                                    <h1>Przykładowy tekst</h1>
                                </div>
                            </div>

                            <div className="icon_border_round">
                                <a href="#section_1"><img src={"/assets/images/ic_arrow_up_gradient.png"}/></a>
                            </div>
                        </div>
                    </div>
                </section>
            </React.Fragment>
        )
    }
};

I more or less know how to do it.

I found this question: Check if element is visible on screen

It has a great answer, which points to this fiddle: http://jsfiddle.net/t2L274ty/1/

Code from the answer

window.onscroll = function() {
  wrapper.style.backgroundColor = checkVisible(tester) ? '#4f4' : '#f44';
};

function checkVisible(elm) {
  var rect = elm.getBoundingClientRect();
  var viewHeight = Math.max(document.documentElement.clientHeight, window.innerHeight);
  return !(rect.bottom < 0 || rect.top - viewHeight >= 0);
}

So my question is where should I put this kind of code? In componentDidMount() or maybe render()? What would be the React way of doing things?

6
  • 2
    stackoverflow.com/questions/29725828/… I would check in a way similar to the answer of this question Commented Jun 12, 2018 at 13:00
  • 1
    render() may trigger multiple times, whereas componentDidMount only once, so Joe's link should help you. Commented Jun 12, 2018 at 13:01
  • Although, you may want to throttle the scroll event with something like Rx.js or whatever Commented Jun 12, 2018 at 13:01
  • @Joe, just out of curiosity, how did you find the question you linked? While it does answer my question it's asking about something different, and I'd never think to search it like this. Commented Jun 12, 2018 at 13:12
  • 1
    I've implemented something similar in knockoutjs awhile ago. I search 'React onscroll' or something similar. Commented Jun 12, 2018 at 16:53

1 Answer 1

5

You would put your event code in componentDidMount and also componentWillUnmount.

componentDidMount() {
   window.addEventListener('scroll', this.onWindowScroll);
}

componentWillUnmount() {
  window.removeEventListener('scroll, this.onWindowScroll);
}

onWindowScroll = debounce(() => { // assuming you're using https://babeljs.io/docs/plugins/transform-class-properties/
  console.log('Debounced scroll event');
}, 100)

If you want to only listen to the scroll event once and you have multiple of these components you can be a bit more clever about it but not sure of your use case.

Sign up to request clarification or add additional context in comments.

3 Comments

Edit: Nevermind someone linked to something with basically the same answer
I will still select as best, since the question is quite different. It just happens to be solved by the same answer.
Thanks @alex.iron ;)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.