0

I am trying to change the url while scrolling the page.

I am using jQuery .scroll() for that. The problem is that this on $(this) grabs the context of the React component. How can I change this code to make it work?

import React from 'react';
import $ from 'jquery';

class Main extends React.Component {
  componentDidMount() {
    $(() => {
      let currentId = 'about';

      $(document).scroll(() => {
        $('.path').each(() => {
          const top = window.pageYOffset;
          const distance = top - $(this).offset().top;
          const path = $(this).attr('id');

          if (distance < 50 && distance > -50 && currentId !== path) {
            window.history.pushState(null, null, '/' + path);
            currentId = path;
          }
       });
      });
     }); 
  }

 render() {
     return (
       <main role="main">
         <About />
         <Contact />
       </main>
     );
   }
 }


export default Main;

The error: enter image description here

Just as a complement, I am following these 'helpers' and adapt them to my needs:

viery365
  • 935
  • 2
  • 12
  • 30
  • You are right. It's a mistake. I will correct it. – viery365 Jul 02 '18 at 14:50
  • Is the wrapping ` $(() => { //... }` in your `componentDidMount` the same as the regular jQuery `document.ready` function? If so, your code is never going to run since your component will mount after the `document.ready` event fires. – mccambridge Jul 02 '18 at 14:57
  • @mccambridge a document ready will execute immediately if it has already reached the point that the page has already loaded. – Taplar Jul 02 '18 at 14:59
  • Just as a complement: I am following this jsFiddle and adapt it to my needs: http://jsfiddle.net/gugahoi/2ZjWP/8/ – viery365 Jul 02 '18 at 15:01
  • 1
    @mccambridge http://jsfiddle.net/va2nwujs/ – Taplar Jul 02 '18 at 15:01
  • @mccambridge I removed the wrapper and the same error appears as before: TypeError: elem.getClientRects is not a function. Than it points to `const distance = top - $(this).offset().top;` where the execution blocks. – viery365 Jul 02 '18 at 15:07
  • @Taplar my mistake. Been a while since I jQuery'd regularly ;) – mccambridge Jul 02 '18 at 15:11

2 Answers2

1

Just use normal function when you need dynamic context

$('.path').each(function() {
          const top = window.pageYOffset;
          const distance = top - $(this).offset().top;
          const path = $(this).attr('id');

          if (distance < 50 && distance > -50 && currentId !== path) {
            window.history.pushState(null, null, '/' + path);
          }
       });
Yury Tarabanko
  • 44,270
  • 9
  • 84
  • 98
  • I will try it out. Thank you:) – viery365 Jul 02 '18 at 14:56
  • It doesn't work unfortunately. I receive always the same error as before: TypeError: elem.getClientRects is not a function. Than it points to `const distance = top - $(this).offset().top;` where the execution blocks. – viery365 Jul 02 '18 at 15:05
  • @Luca Fabbri I had to rollback your edit because it goes against my idea. `this` inside `$('.path').each` callback is dom element. – Yury Tarabanko Jul 02 '18 at 15:48
0

So, the solution is the accepted answer. The problem had to do with the way I was adding the anonymous function as a parameter for the .each() method. Instead of () => {...}, use function(){...}.

$(() => {
      let currentPath = '';
      $(document).scroll(() => {
        $('.path').each(function () {
          const top = window.pageYOffset;
          const distance = top - $(this).offset().top;
          const path = $(this).attr('id');

          if (distance < 30 && distance > -30 && currentPath != path) {
            window.history.replaceState(`/${path}`, 'Title', `/${path}`);
            currentPath = path;
          }
        });
      });
    });
viery365
  • 935
  • 2
  • 12
  • 30