Skip to content
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

Issue with router and InfiniteScroll #295

Closed
ferrannp opened this issue Sep 17, 2014 · 8 comments
Closed

Issue with router and InfiniteScroll #295

ferrannp opened this issue Sep 17, 2014 · 8 comments

Comments

@ferrannp
Copy link

I am not sure if this is the proper place to write this but here you go. I am using the infinite scrolling component from https://github.com/vjeux/react-infinite-scroll/blob/master/src/react-infinite-scroll.js

When I use react-router and I write the url of my website like: http://xxx.index.html, the react-router is changing it to http://xxx.index.html#/ and this is making that the function "loadMore" from InfiniteScroll component gets called twice! (so I am fetching twice from my server).

Instead, if I write the url as http://xxx.index.html#/ directly, it works fine. Any idea of why this is happening and how to solve it?

@gaearon
Copy link
Contributor

gaearon commented Sep 19, 2014

Does this happen with <Routes location="history">? Just curious why you're using hashes—do you need to support older browsers?

@ryanflorence
Copy link
Member

With hash location we push /# into the url so that you don't have two urls with the same view. I suspect that's the reason you get two mounts.

Maybe we should be able to do this w/o causing two renders.

@mjackson
Copy link
Member

The two-render problem is one that a lot of people have asked about and I've answered the question several times. I'm going to explain the mechanics of it here once more, and then remember this issue # to point people to it who ask about it in the future ;)

When you call React.renderComponent(<Routes>, ... ), the following things happen:

  1. React mounts the component. This includes calling componentWillMount on your <Routes>, as well as render. This is the first render. However, since no transition has taken place yet your <Routes> simply render nothing (i.e. null).
  2. Inside Routes#componentWillMount we kick off a transition to the current URL. Of necessity, transitions are asynchronous. This gives route handlers the ability to fetch data or make a call to the server before deciding if they need to abort or redirect the transition.
  3. Sometime later, the transition completes. At this point the router updates the props of your <Routes> component to let it know what routes are currently active so it can render the page.

Honestly, I've never understood why this is such a problem for people. One of the expectations of render is that it is called by the framework (i.e. React) whenever the framework feels like it. You shouldn't be writing code that anticipates the # of times render will be called or works differently depending on when it is called. Instead, render should simply describe the end state of the DOM.

@Difort The infinite scroll script that you're using uses the loader prop inside render to get a descriptor of an element to display while you're loading more content. This element should always be consistent, probably a spinner or something. But you shouldn't be using the loader prop to actually load data. The loadMore function only gets called when the element scrolls, so it shouldn't be getting called when the page simply renders twice. If it is, there's the source of your problem.

@rpflorence If we did want to make the router only render once on initial page load, we could do one of 2 things:

  1. Make transitions sync instead of async.
  2. Make users manually run the initial transition before calling React.renderComponent.

Since neither of these are very good options, and since render should be totally resilient to being called many times (or only once), I opted to go the route I did. Please feel free to reopen if you think this is something that needs to be changed.

@bobeagan
Copy link
Contributor

Maybe worthwhile to add a FAQ page to the docs and pull out gems such as this ^^^ and include it there so that people don't have to dig through closed issues to find helpful information and explanations?

@ryanflorence
Copy link
Member

Yeah, we need an FAQ.

mjackson added a commit that referenced this issue Sep 25, 2014
[removed] Ability to return a promise from willTransition* hooks

This commit makes async transitions entirely optional. Users
opt-in to using asynchronous transitions using transition.wait(promise).

Fixes #309
Fixes #300
Fixes #295
@jedwards1211
Copy link

So this happened to me, turns out the second willTransitionTo() did a redirect but the first one didn't, yet the second one's redirect never took effect. I think I will just add code to make it ignore the second willTransitionTo()...

@jothikg
Copy link

jothikg commented Jan 26, 2016

I am facing this similar issue and causing browser back button issue eg. I am navigating from View page (http://localhost:3000/) to Edit page (http://localhost:3000/editCard/1234) via dispatch(routeActions.push(/editCard/1234)), so it first navigate it to http://localhost:3000/editCard/panGuid1# and then http://localhost:3000/editCard/1234, when the user clicks browser back button. The page are navigating from the below sequence.

http://localhost:3000/editCard/1234
http://localhost:3000/editCard/1234# - Unnecessary navigation
http://localhost:3000/

Expected behaviour should be http://localhost:3000/editCard/1234 -> http://localhost:3000/

is there any fix for this?

@jothikg
Copy link

jothikg commented Jan 28, 2016

Any updates on my above question?

@lock lock bot locked as resolved and limited conversation to collaborators Jan 22, 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

7 participants