0

I have a route like so:

<BrowserRouter>
      <Switch>
        <Route path="/question/:title" component={Item} />
      </Switch>
    </BrowserRouter>

The component uses axios to fetch data and update the content on the site, this is done in the componentWillMount function:

componentWillMount(){
        const {title} = this.props.match.params;
        axios.get(server + '/api/question/slug/' + title)
                .then(response => {
                    this.setState({
                        question: response.data,
                        loading: false
                    })

                })
    }

The problem now is that, let's say I'm on a page "site.com/question/this-is-an-article", and I use <Link to="/question/second-article">Second Article</Link> to navigate, it's like the componentWillMount function is not being called so the former content still remains on the page. How can I make the componentWillMount function to run when there is a change in the url?

norbitrial
  • 14,716
  • 7
  • 32
  • 59
Nengak dakup
  • 88
  • 2
  • 11
  • possible duplicate of https://stackoverflow.com/questions/38915066/on-url-change-i-want-to-re-render-my-component-how-should-i-do-that/38916204 and https://stackoverflow.com/questions/52252353/re-render-same-component-on-url-change-in-react/53509329 – Andy Nov 03 '20 at 14:53

3 Answers3

2

First of all, use safe life-cycle is preferred react-lifecycle-methods-diagram

Since you are using react-router-dom, you can get your URL via render props like this, refer to document here

history.location.pathname

So you may try to check if url changed in shouldComponentUpdate like this

shouldComponentUpdate(prevProps, prevState) {
  return this.props.history.location.pathname !== prevProps.history.location.pathname
}

You can add more condition inside of it, or just prevent complex condition via component design adjustment

keikai
  • 14,085
  • 9
  • 49
  • 68
  • `shouldComponentUpdate` should not be a goto for this; In asker's case, when the `title` is changing - the component is getting newer props for the updated title - only it is not reacting to those updated props. Methods like `componentDidUpdate`/`componentWillReceiveProps`(if using older version otherwise use UNSAFE aptly)/`getDerivedStateFromProps` are better fitting for updating state based on props. – H S Dec 21 '19 at 14:16
  • @HS That's the reason why those lifecycles are not preferred, since updating state based on props is not recommended, which you may refer to this [QA](https://stackoverflow.com/questions/40063468/react-component-initialize-state-from-props) – keikai Dec 21 '19 at 14:21
  • then what you intend to do with checking if the url is changed via `shouldComponentUpdate` in your answer - wont you change the state of mounted component with newer response triggered by a newer 'prop'. – H S Dec 21 '19 at 14:28
0

Try using the componentDidUpdate for the axios calling. Necessarily - you want to call the api when title(a prop) parameter change.

You may also try componentWillReceiveProps/UNSAFE_componentWillReceiveProps for the same.

P.S. - use componentDidMount along with above aptly. Look for lifecycle here http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/

H S
  • 735
  • 4
  • 12
  • does 'componentDidUpdate' run on the first time/initial render? – Nengak dakup Dec 21 '19 at 14:31
  • @Nengakdakup you may check more about life-cycles here - http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/; – H S Dec 21 '19 at 14:35
  • @Nengakdakup - in relation to the answer, it points towards the concern of having axios called as a result of updated props. – H S Dec 21 '19 at 14:38
0

I think you don't need any life cycle, (if yes, just use componentDidMount):

class App extends Component {
  constructor() {
    super();
    this._initHistoryListen();
  }
  _unListen = () => {};
  _initHistoryListen() {
    this._unListen = history.listen((location, action) => {
      const {
        title
      } = this.props.match.params;
      axios.get(server + '/api/question/slug/' + title)
        .then(response => {
          this.setState({
            question: response.data,
            loading: false
          })

        })
    });
  }
  componentWillUnmount(){
     this._unListen()
  }
}

Alvin
  • 298
  • 2
  • 14