Skip to content

"withRouter" doesn't rerender elements when state is changed #4676

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jfarid27 opened this issue Mar 10, 2017 · 4 comments
Closed

"withRouter" doesn't rerender elements when state is changed #4676

jfarid27 opened this issue Mar 10, 2017 · 4 comments

Comments

@jfarid27
Copy link
Contributor

Version

4.0.0-beta.8
Node: 6.6.9

Test Case

Ping me if you really want one. I can probably deploy something on heroku since this test depends on the browser url and I don't have access to it in jsbin.

Steps to reproduce

  1. Create an example app with BrowserRouter
  2. Create a component and use jsx to show { this.props.location.pathname } in the html.
  3. Use withRouter on the component and render.

Expected Behavior

I expect to see the component rerender on a history state change, but this doesn't seem to happen.

Actual Behavior

Component does not rerender. You can see this by adding a console.log in the render or using the jsx method described above.

Current Fix

This seems to work when rolling back react-router and react-router-dom to 4.0.0-beta.6. The withRouter then does have history context and works as intended. I'm not sure but it seems as if beta.8 introduced a bug.

@pshrmn
Copy link
Contributor

pshrmn commented Mar 10, 2017

You are either using shouldComponentUpdate (directly or indirectly through something like react-redux or mobx-react) or React.PureComponent. These are blocking your application from fully updating on location changes. Please see the blocked updates guide for more information.

@jfarid27
Copy link
Contributor Author

@pshrmn can we reopen this and check out PR #4684. I'd love to add to the documentation about this issue. It was pretty non-intuitive but after your explanation, I think it would be worth adding to the docs.

@esamattis
Copy link
Contributor

esamattis commented Mar 13, 2017

This is really confusing.

I'm constantly hitting this issue and the workarounds seem to be ugly. I often have an intermediate component which implements shouldComponentUpdate via PureComponent and I have go and make it aware of the router even if it does not use the router at all.

Why the withRouter HOC or the Route component cannot directly listen to the location changes? Bit like connect() in react-redux listens to the store changes via context. It does not break when put as a child of an pure component.

I also find the blocked-updates.md documentation weird because the proposed solution is to add withRouter but it is itself affected the by the issue.

@esamattis
Copy link
Contributor

esamattis commented Mar 13, 2017

It's impossible for me to make every pure component aware of the react-router so I made following workaround:

class ListeningRoute extends React.Component {
    componentWillMount() {
        this.unlisten = this.props.history.listen(location => {
            this.setState({location});
        });
    }

    componentWillUnmount() {
        this.unlisten();
    }

    render() {
        return <Route {...this.props}  location={this.state.location} />;
    }
}
ListeningRoute = withRouter(ListeningRoute);

This ListeningRoute component works exactly like the default Route but it does render when it's a child of an pure component.

This works because the Route component can get the location pathname from the location prop as well as from the router context:

https://github.com/ReactTraining/react-router/blob/a3362060a9e349b3356eec548b03af13b9c37cc8/packages/react-router/modules/Route.js#L56

UPDATE: Let's continue in #4671

@lock lock bot locked as resolved and limited conversation to collaborators Jan 20, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants