React Router ScrollToTop not working with Material UI

时间:2018-09-18 19:41:51

标签: reactjs react-router material-ui

I'm using Material UI for a fairly simple website but I'm having trouble with ScrollToTop. I've followed the documentation but can't seem to find the issue with my code. The desired functionality is every time a link is clicked, the page loads at the top. Instead, when clicked, the page changes but is rendered in the same position as the previous. See below - I've simplified the code so you aren't blasted with a wall of text.

Documentation referenced: https://reacttraining.com/react-router/web/guides/scroll-restoration

Root Component

const homePage = () => (<Home />);
const helpPage = () => (<Help />);
const termsPage = () => (<Markdown>{terms}</Markdown>);
const privacyPage = () => (<Markdown>{privacy}</Markdown>);

class Header extends React.Component {

  componentDidUpdate(prevProps) {
    if (this.props.location !== prevProps.location) {
      window.scrollTo(0, 0);
    }
  }

  render() {
    return (
      <MuiThemeProvider theme={darkTheme}>
        <div className={classes.root}>
          <AppBar position="absolute" className={classes.appBar}>
            <Toolbar>
              <Link className={classes.link} to="/"><Typography>Home</Typography></Link>
              <Link className={classes.link} to="/help"><Typography>Help</Typography></Link>
              <IconButton onClick={this.props.logOut} className={classes.headerIcon}>
                <AccountCircleIcon />
              </IconButton>
            </Toolbar>
          </AppBar>
          <main className={classes.content}>
            <div className={classes.toolbar} />
            <Route exact path="/" component={homePage} />
            <Route path="/help" component={helpPage} />
            <Route path="/terms" component={termsPage} />
            <Route path="/privacy" component={privacyPage} />
            <Footer />
          </main>
        </div>
      </MuiThemeProvider>
    );
  }
}

1 个答案:

答案 0 :(得分:1)

I discovered the root of the issue. The ScrollToTop function was referencing the window, but the content in question was being rendered in the main element under the Material UI Header. My solution was to reference the main element - problem solved. See below.

class Header extends React.Component {
  main = null;

  componentDidUpdate(prevProps) {
    if (this.props.location !== prevProps.location) {
      this.main.scrollTo(0, 0);
    }
  }

  render() {
    return (
      <MuiThemeProvider theme={darkTheme}>
        <div className={classes.root}>
          <AppBar position="absolute" className={classes.appBar}>
            <Toolbar>
              <Link className={classes.link} to="/"><Typography>Home</Typography></Link>
              <Link className={classes.link} to="/help"><Typography>Help</Typography></Link>
              <IconButton onClick={this.props.logOut} className={classes.headerIcon}>
                <AccountCircleIcon />
              </IconButton>
            </Toolbar>
          </AppBar>
          <main ref={(ref) => { this.main = ref; }} className={classes.content}>
            <div className={classes.toolbar} />
            <Route exact path="/" component={homePage} />
            <Route path="/help" component={helpPage} />
            <Route path="/terms" component={termsPage} />
            <Route path="/privacy" component={privacyPage} />
            <Footer />
          </main>
        </div>
      </MuiThemeProvider>
    );
  }
}

----Edits---- Using React.createRef() as suggested by Pier

class Header extends React.Component {
 constructor(props) {
    super(props);
    this.main = null;
    this.setMainRef = (element) => {
      this.main = element;
    };
  }

  componentDidUpdate(prevProps) {
    if (this.props.location !== prevProps.location) {
      this.main.scrollTo(0, 0);
    }
  }

  render() {
    return (
      <MuiThemeProvider theme={darkTheme}>
        <div className={classes.root}>
          <AppBar position="absolute" className={classes.appBar}>
            <Toolbar>
              <Link className={classes.link} to="/"><Typography>Home</Typography></Link>
              <Link className={classes.link} to="/help"><Typography>Help</Typography></Link>
              <IconButton onClick={this.props.logOut} className={classes.headerIcon}>
                <AccountCircleIcon />
              </IconButton>
            </Toolbar>
          </AppBar>
          <main ref={this.setMainRef} className={classes.content}>
            <div className={classes.toolbar} />
            <Route exact path="/" component={homePage} />
            <Route path="/help" component={helpPage} />
            <Route path="/terms" component={termsPage} />
            <Route path="/privacy" component={privacyPage} />
            <Footer />
          </main>
        </div>
      </MuiThemeProvider>
    );
  }
}