Johnny88520
Johnny88520

Reputation: 157

react-scrollable-anchor is not working properly

npm react-scrollable-anchor for some reason not working properly. I can only jump to the id attribute only in <section> tag, not sure why.

I have tried libraries including, react-scrollable-anchor, react-anchor-link-smooth-scroll, and react-scrollchor. None of them working properly. I can at most see that there is a hash tag in my url, but page doesn't scroll at all. I have to use <section> tag in order to jump to the section. Other than that, my page doesn't move at all. I'm assuming that I don't need to react-router in order to achieve scrolling.

import React, { Component } from 'react';
import { Button } from 'react-bootstrap';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import Welcome from './sections/welcome/welcome';
import Artists from './sections/artists/homepageArtists';

import ScrollableAnchor from 'react-scrollable-anchor';
import { configureAnchors } from 'react-scrollable-anchor'
import PropTypes from "prop-types";
import './Home.css';

const dots = [
{ className: 'navDots', name: 'Welcome', section: "#welcome", num: '1', to:"#welcome"},
{ className: 'navDots', name: 'Artists', section: "#artists", num: '2', to:"#artists"},
]

class PageSection extends Component {
    render() {
        return this.props.content;
    }
}

PageSection.propTypes = {
    content: PropTypes.node.isRequired
}

class Home extends Component {
    render() {

    return (
        <div>

            <div className="homepage">
                <div className="homepage-title">
                    <div className="dots-group">
                        {dots.map((dot) => (
                            <span className={dot.className} key={dot.name}>
                                <a href={dot.section}> go </a>
                            </span>
                        ))}
                    </div>
                </div>

            </div>


            <ScrollableAnchor id={"welcome"}>
                <PageSection content={<Welcome />} />
            </ScrollableAnchor>
            <ScrollableAnchor id={"artists"}>
                <PageSection content={<Artists />} />
            </ScrollableAnchor>

            <section id='welcome'>
                <PageSection content={<Welcome />} />
             </section>
             <section id='artists'>
                <PageSection content={<Artists />} />
             </section> 
        </div>
     }
   }
}

I expect that it should scroll to the id section when I click the anchor tag. My react version is 16.5.2 if this matters?

Upvotes: 3

Views: 3410

Answers (1)

Oluwafemi Sule
Oluwafemi Sule

Reputation: 38982

ScrollableAnchor in react-scrollable-anchor library forwards refs for its children when it renders.

render() {
  const {children, id} = this.props

  return React.cloneElement(children, {
    ref: children.ref || id,
  })
}

View Source

When scrollable anchors are implemented with stateless functional components like so

const Welcome = props => {
  return (<div {...props}>Welcome!</div>)
}

const Artists = props => {
  return (<div {...props}>These are artists!</div>)
}

const App = () => (
  <div>
    <ScrollableAnchor id={"welcome"}>
      <Welcome style={{ height: 600 }}/>
    </ScrollableAnchor>
    <ScrollableAnchor id={"artists"}>
      <Artists style={{ height: 800 }} />
    </ScrollableAnchor>
  </div>
)

There is a console warning that must be given attention to:

Warning: Stateless function components cannot be given refs. Attempts to access this ref will fail.

Check the render method of ScrollableAnchor.

in Welcome (created by ScrollableAnchor)

in ScrollableAnchor (created by App)

in div (created by App)

in App

Refs are not allowed to be set on stateless components since they don't have instances. Refer to this StackOverflow answer for more conversation about that.

To address this warning, you can either implement the stateless components as stateful ones or create a stateful container as below:

class PageSection extends Component {
   render() {
     return this.props.content
   }
}
PageSection.propTypes = {
  content: PropTypes.node.isRequired
}

This above PageSection stateful container can be used in the App component as follow.

<ScrollableAnchor id={"welcome"}>
  <PageSection content={<Welcome style={{ height: 600 }}/>} />
</ScrollableAnchor>
<ScrollableAnchor id={"artists"}>
  <PageSection content={<Artists style={{ height: 800 }}/>} />
</ScrollableAnchor>

Here is a StackBlitz with the complete code.

Since react-scrollable-anchor was developed for React 15, it uses deprecated API of ReactDOM such as findDOMNode that may removed in later versions of React 16 so I suggest to look to informing the maintainers about that and possibly contributing an update.

Upvotes: 1

Related Questions