Open govind999 opened 8 years ago
@govind999 1) by gadgets if you mean Widgets then the load is being called in https://github.com/erikras/react-redux-universal-hot-example/blob/master/src/containers/Widgets/Widgets.js
@asyncConnect([{
deferred: true,
promise: ({store: {dispatch, getState}}) => {
if (!isLoaded(getState())) {
return dispatch(loadWidgets());
}
}
}])
2) The app component is loaded only once in this example ( its the navbar ) and it remains throughout the entire app so I think you can use that. In https://github.com/erikras/react-redux-universal-hot-example/blob/master/src/containers/App/App.js you can find the below code where multiple actions are being dispatched ( multiple rest calls can be made as well )
@asyncConnect([{
promise: ({store: {dispatch, getState}}) => {
const promises = [];
if (!isInfoLoaded(getState())) {
promises.push(dispatch(loadInfo()));
}
if (!isAuthLoaded(getState())) {
promises.push(dispatch(loadAuth()));
}
return Promise.all(promises);
}
}])
The third question it is not clear, There is an api server in this example which runs on port 3030. ( and you can modify that ). If you want to call a standalone api server you can just change the proxy settings in server.js and ApiClient.js or just proxy all requests from the api server.
Thanks for the response. What i mean to ask is
instead of calling /api/ which is running on same server i can call any restful webservices right? for me that call should work both on client and server, i don't want the ajax calls on client going via node.
@govind999 A page which uses rest calls to show data will have to make that call either in the server or client.
If you open that page directly it will be called from server and not from client ( as the page is rendered on server side and the same data is carried forward to the client).
If you load a different page and then go to the page with the call, it will call the api through ajax to get the data to render the page.
If your app is running in http://xxx:3000 then only requests to http://xxx:3000 will normally be allowed by the browser. So you can't call some other domain's api without them allowing permission via adding the allow cross origin header so if you use this example the requests will have to be through node ( you can proxy them to match your needs though).
A workaround would be if your app server is behind another server like nginx you can write rules that allow a few requests to go to your app and the others to go to the api server.
@VSuryaBhargava Can you achieve the second point you mentioned (in your first comment),from the action creator themselves?
So, something like this?
//in loadAuth function for example:
return {
id: 1,
types: [
AUTH_REQUESTED,
AUTH_REQUEST_SUCCESS,
AUTH_REQUEST_FAIL
],
promise: (client) =>
client.get(requestQuery())
.then(() => loadInfo())
};
This doesn't work for me but I was wondering if you've had any luck with that?
@VSuryaBhargava
I will give it a try today,
most of API calls are CORS enabled. So there is no need to go via /api unless its required. We had one project in Fluxible which use fetcher and it calls /api/ and that inturn calls the restful api. I want to avoid the extra hop from browser which can has performance gain.
because client browser and node server are going to be at different places.
@oyeanuj
In your example I think the promise will resolve with the value that loadInfo is returning, so make sure that its returning some value that the reducers can use.
If you are trying to call multiple api's you can just create a promise like below
return {
id: 1,
types: [
AUTH_REQUESTED,
AUTH_REQUEST_SUCCESS,
AUTH_REQUEST_FAIL
],
promise: (client) => {
return new Promise((resolve, reject) => {
client.get(requestQuery()).then((mainData) => {
// conditions
client.get(requestAnotherQuery()).then((additionalData) => {
// conditions
if (conditions) {
resolve({mainData, additionalData});
} else {
reject({mainData, additionalData});
}
})
})
});
}
};
Is there any reason to wait till the first api call has ended? if not you can just use Promise.all() to combine bith the api calls into a single promise.
I still think that dispatching multiple actions will be the best way to go ( unless the second call depends on the data from the first ).
@VSuryaBhargava Thanks for the snippet, I'll try it out.
As for your other queries, I have to wait till the first api call has ended since the second call is conditional - if certain information is not fetched, fetch another set of information. And I've been trying to not dispatch multiple actions or chain them since then it becomes integrated with the component where the action is being dispatched. Ideally, for me, it would be the concern of action-creator to have conditional promises or API calls.
Essentially, to sum it up, I guess, I am looking for being able to set up conditional API calls within an action creator?
@VSuryaBhargava The only problem with the above snippet is that I'd have to create that query in this action creator. Ideally, I'd like to dispatch a different action from the then
of the API promise.
@oyeanuj , my usecase is also exactly same, i need to call the parent call first and if that succeeds, grab data from there and call another api call, Can you document once it works for you?
Or is it all calls should be tied to components or is there anyway we can fire the root api call on some kind of load?
@oyeanuj
I got it to work in this way, I passed the dispatch function from @asyncConnect in src/containers/Widgets.js
@asyncConnect([{
deferred: true,
promise: ({store: {dispatch, getState}}) => {
if (!isLoaded(getState())) {
return dispatch(loadWidgets(dispatch));
}
}
}])
and in the src/redux/modules/widgets.js
I moved the load function below the save function, the load function now accepts dispatch as a parameter
export function load(dispatch) {
return {
types: [LOAD, LOAD_SUCCESS, LOAD_FAIL],
promise: (client) => client.get('/widget/load/param1/param2').then((data) => {
// condition
if (data[0].owner !== 'John Connor') {
const newData = {
...data[0],
owner: 'John Connor'
};
dispatch(save(newData));
}
return data;
})
};
}
@VSuryaBhargava thanks so much, i will take a look at that, by the way is this command working for you node ./node_modules/mocha/bin/mocha $(find api -name '*-test.js'), it throws error at $(find may be it is mac syntax
I got this working, it should be updated as below
"test-node": "node ./node_modules/mocha/bin/mocha ./api/__tests__/*.js --compilers js:babel-core/register",
@oyeanuj
Just came across this https://github.com/gaearon/redux-thunk
I think this is what you are looking for.
Hi All,
Couple of questions.