react-scrollable-anchor icon indicating copy to clipboard operation
react-scrollable-anchor copied to clipboard

Url hash is changing, but viewport not scrolled

Open indapublic opened this issue 7 years ago • 5 comments

Hi. I have 15 React and 3 React Router. Do you supported it?

"react": "^15.4.2",
"react-router": "^3.0.2",

I have this markup:

<ul className="links">
          <li>
            <a href="#link1">
              Link 1
            </a>
          </li>
          <li>
            <a href="#link2">
              Link 2
            </a>
          </li>
          <li>
            <a href="#link3">
              Link 3
            </a>
          </li>
          <li>
            <a href="#link4">
              Link 4
            </a>
          </li>
          <li>
            <a href="#link5">
              Link 5
            </a>
          </li>
        </ul>
<ScrollableAnchor id={"link1"}>
          <div>
.......
          </div>
        </ScrollableAnchor>

So it's not working. No errors in console. Url hash is changing, but viewport not scrolled

indapublic avatar May 10 '17 23:05 indapublic

@indapublic same here, the component doesn't work also with RR v4.

JonatanSalas avatar Jun 05 '17 13:06 JonatanSalas

I have ended up with my own solution:

import React from 'react';
import { withRouter } from 'react-router-dom';

class ScrollToAnchors extends React.Component {
    componentDidUpdate(prevProps) {
        if (this.props.location !== prevProps.location) {
            const element = document.querySelector(this.props.location.hash);

            if (element) {
                element.scrollIntoView({
                    behavior: 'smooth'
                });
            }
        }
    }

    render() {
        return this.props.children;
    }
}

export default withRouter(ScrollToAnchors);

Also, for supporting smooth-scroll in all browsers I have added a polyfill.

UPDATE:

You can also use Jump.js and refactor the previous component to this new one:

import React from 'react';
import jump from 'jump.js';
import { withRouter } from 'react-router-dom';

class ScrollToAnchors extends React.Component {
    componentDidUpdate(prevProps) {
        if (this.props.location !== prevProps.location) {
            const element = document.querySelector(this.props.location.hash);

            if (element) {
                jump(element, {
                    duration: this.props.duration || 500,
                    offset: this.props.offset || 0,
                    callback: this.props.callback || undefined,
                    a11y: this.props.a11y || false
                });
            }
        }
    }

    render() {
        return this.props.children;
    }
}

export default withRouter(ScrollToAnchors);

JonatanSalas avatar Jun 05 '17 14:06 JonatanSalas

@JonatanSalas Thank, Jonatan! I will try it sometime later.

indapublic avatar Jun 06 '17 02:06 indapublic

You're welcome. Here I leave the correct code snippet. I have modified react-router-dom import to react-router. In this way, this code should work with react-router v2, v3 and v4.

import React from 'react';
import PropTypes from 'prop-types';
import jump from 'jump.js';
import { withRouter } from 'react-router';

@withRouter
export default class ScrollableAnchor extends React.Component {
    static propTypes = {
        duration: PropTypes.number,
        offset: PropTypes.number,
        callback: PropTypes.func,
        a11y: PropTypes.bool
    };

    static defaultProps = {
        duration: 500,
        offset: 0,
        callback: undefined,
        a11y: false
    };

    componentDidUpdate(prevProps) {
        if (this.props.location !== prevProps.location) {
            const element = document.querySelector(this.props.location.hash);

            if (element) {
                jump(element, {
                    duration: this.props.duration,
                    offset: this.props.offset,
                    callback: this.props.callback,
                    a11y: this.props.a11y
                });
            }
        }
    }

    render() {
        return this.props.children;
    }
}

JonatanSalas avatar Jun 06 '17 11:06 JonatanSalas

I had the same problem. Do you have a fixed navigation and the content is overlapped, so it isn't visible - but shown under the navbar?

This worked for me:

import { configureAnchors } from 'react-scrollable-anchor'; configureAnchors({ offset: -64 });

sholzmayer avatar Aug 02 '17 08:08 sholzmayer