简体   繁体   中英

Refresh Component on route parameter change

Why the component doesn't update the props when changing the route param?

Trying to use setState inside componentWillReceiveProps but it doesn't even fire?

export default class HomePage extends React.PureComponent {
  movies = require('../../movieList.json');
  state = {
    match: this.props.match,
    id: null
  }

  componentWillReceiveProps(np) {
    if(np.match.params.id !== this.props.match.params.id) {
      console.log('UPDATING PROPS')
      this.setState({ match: np.match })
    }
  }

  render() {
    const { match } = this.props;

    const movie = this.movies[match.params.id || movieOrder[0]];
    const nextMovie = getNextMovie(match.params.id || movieOrder[0]);
    const prevMovie = getPrevMovie(match.params.id || movieOrder[0]);
    return (
      <>
        <h1>{movie.title}</h1>
        <Link to={nextMovie}>Next</Link>
        <Link to={prevMovie}>Prev</Link>
      </>
    );
  }
}

nextMovie and prevMovie get the id which should be set inside link. Unfortunatelly it sets only during 1st render. When clicked I can see the url change, but no updates are fired

Here is the component holding the switch

export default class App extends React.PureComponent {

  state = {
    isLoading: true,
  }

  componentDidMount() {
    PreloaderService.preload('core').then(() => {
      console.log('LOADED ALL');
      console.log('PRELOADER SERVICE', PreloaderService);
      this.setState({ isLoading: false });
      console.log('Preloader assets', PreloaderService.getAsset('dog-video'))
    });
  }

  render() {
    const { isLoading } = this.state;

    if(isLoading) {
      return(
        <div>
          is loading
        </div>
      )
    }
    return (
      <div>
        {/* <Background /> */}
        <Switch>
          <Route exact path="/" component={HomePage} />
          <Route exact path="/:id" component={props => <HomePage {...props} />} />
          <Route component={NotFoundPage} />
        </Switch>
        <GlobalStyle />
      </div>
    );
  }

}```

There are several things off here. componentWillReceiveProps is considered unsafe and is deprecated . Try using componentDidUpdate instead . Also your class component needs a constructor . As it is now state is defined as a static variable.

constructor(props) {
  super(props);
  this.state = {
    match: this.props.match,
    id: null
  }
}

componentDidUpdate(np) {
  if(np.match.params.id !== this.props.match.params.id) {
    console.log('UPDATING PROPS')
    this.setState({ match: np.match })
  }
}

Last, double check to make sure your logic is correct. Right now the Next and Prev buttons link to the same thing:

const nextMovie = getNextMovie(match.params.id || movieOrder[0]);
const prevMovie = getPrevMovie(match.params.id || movieOrder[0]);

<Link to={nextMovie}>Next</Link>
<Link to={prevMovie}>Prev</Link>

As an alternative, if you want to stick with componentWillReceiveProps you need to unbind the current movie, and rebind it with a new one. Here is a code example doing the exact same thing with users.

Seems to be working with my codesandbox recreation .

I had to improvise a bit with the missing code:

What's the value of movieOrder[0] ? Is 0 a valid value for match.params.id ?

How do getNextMovie and prevMovie look like?

Also, you're not using the Home component's state in your render logic, so I think, it should render the correct movie even without them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM