-
Notifications
You must be signed in to change notification settings - Fork 3
fetchData() and fetchDataDeferred() behave as they should #4
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,17 +9,17 @@ import createStore from './redux/create'; | |
import ApiClient from './helpers/ApiClient'; | ||
import io from 'socket.io-client'; | ||
import {Provider} from 'react-redux'; | ||
import {Router} from 'react-router'; | ||
import {Router, match, createRoutes} from 'react-router'; | ||
import {syncReduxAndRouter} from 'redux-simple-router'; | ||
import getRoutes from './routes'; | ||
import {fetchData, fetchDataDeferred} from './helpers/fetchComponentsData'; | ||
import useScroll from 'scroll-behavior/lib/useStandardScroll'; | ||
|
||
const client = new ApiClient(); | ||
|
||
const dest = document.getElementById('content'); | ||
const store = createStore(client, window.__data); | ||
const history = createHistory(); | ||
|
||
syncReduxAndRouter(history, store); | ||
const routes = getRoutes(store); | ||
|
||
function initSocket() { | ||
const socket = io('', {path: '/api/ws', transports: ['polling']}); | ||
|
@@ -36,17 +36,60 @@ function initSocket() { | |
|
||
global.socket = initSocket(); | ||
|
||
function createElement(Component, props) { | ||
if (Component.fetchData) { | ||
Component.fetchData(store.getState, store.dispatch, | ||
props.location, props.params); | ||
const history = useScroll(createHistory)({routes: createRoutes(routes)}); | ||
syncReduxAndRouter(history, store); | ||
|
||
let lastMatchedLocBefore; | ||
let lastMatchedLocAfter; | ||
|
||
history.listenBefore((location, callback) => { | ||
const loc = location.pathname + location.search + location.hash; | ||
if (lastMatchedLocBefore === loc) { | ||
return callback(); | ||
} | ||
return React.createElement(Component, props); | ||
} | ||
|
||
match({routes: routes, location: loc}, (err, redirectLocation, nextState) => { | ||
if (!err && nextState) { | ||
fetchData(nextState.components, store.getState, store.dispatch, | ||
location, nextState.params) | ||
.then(() => { | ||
lastMatchedLocBefore = loc; | ||
callback(); | ||
}) | ||
.catch(err2 => { | ||
console.error(err2, 'Error while fetching data'); | ||
callback(); | ||
}); | ||
} else { | ||
console.log('Location "%s" did not match any routes (listenBefore)', loc); | ||
callback(); | ||
} | ||
}); | ||
}); | ||
|
||
history.listen((location) => { | ||
const loc = location.pathname + location.search + location.hash; | ||
if (lastMatchedLocAfter === loc) { | ||
return; | ||
} | ||
|
||
match({routes: routes, location: loc}, (err, redirectLocation, nextState) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here, in fact for this case I think you just need to use the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using |
||
if (err) { | ||
console.error(err, 'Error while matching route (change handler)'); | ||
} else if (nextState) { | ||
fetchDataDeferred(nextState.components, store.getState, | ||
store.dispatch, location, nextState.params) | ||
.then(() => lastMatchedLocAfter = loc) | ||
.catch((err2) => console.error(err2, 'Error while fetching deferred data')); | ||
} else { | ||
console.log('Location "%s" did not match any routes (listen)', loc); | ||
} | ||
}); | ||
}); | ||
|
||
const component = ( | ||
<Router createElement={createElement} history={history}> | ||
{getRoutes(store)} | ||
<Router history={history}> | ||
{routes} | ||
</Router> | ||
); | ||
|
||
|
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
|
||
function _fetchData(components, getState, dispatch, location, params, deferred) { | ||
const methodName = deferred ? 'fetchDataDeferred' : 'fetchData'; | ||
return components | ||
.filter((component) => component && component[methodName]) // only look at ones with a static fetchData() | ||
.map((component) => component[methodName]) // pull out fetch data methods | ||
.map(fetchDataFoo => | ||
fetchDataFoo(getState, dispatch, location, params)); // call fetch data methods and save promises | ||
} | ||
|
||
|
||
export function fetchData(components, getState, dispatch, location, params) { | ||
return Promise.all(_fetchData(components, getState, dispatch, location, params)); | ||
} | ||
|
||
export function fetchDataDeferred(components, getState, dispatch, location, params) { | ||
return Promise.all(_fetchData(components, getState, dispatch, location, params, true)); | ||
} | ||
|
||
export function fetchAllData(components, getState, dispatch, location, params) { | ||
return fetchData(components, getState, dispatch, location, params) | ||
.then(() => fetchDataDeferred(components, getState, dispatch, location, params)) | ||
.catch(error => console.error(error, 'Error while fetching data')); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you should be using
match
browser-side at all. We should be using ahistory
that has been augmented withuseRoutes
: https://github.com/rackt/react-router/blob/master/docs/API.md#useroutescreatehistoryIn fact you pass
routes
intocreateHistory
but that's not doing anything. You need to also wrapcreateHistory
withuseRoutes
, and then thelisten
signature changes: you get(error, nextState) => {}
instead, and you can just usenextState
to get all the components.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, but this is mainly a work-around for this: remix-run/react-router#2502
I don't think there is any practical drawback in using
match
here, but probably I'm missing something?Besides,
useRoutes
can be applied only tolisten
and not tolistenBefore
, so unless we find another way for pulling the route components inlistenBefore
(e.g. react-router gets a patch), this is the only code I got working.