I am relativity new to react/redux. There for I want to ask a (perhaps a philosophic) question.
Is it ok to to dispatch an action (e.g. to trigger an api-call) on
Yes, you should definately use the componentDidMount hook.
A typical use case might be :
I know its a bit long, but I was working myself on this type of problem for a while, so I thought I would share the following pattern ;)
When the component mounts then a fetch data action is triggered. An 'isFetching' value in the application state determines whether the spinner is shown or not (I think i used 'advanced-loader' or some such library)
export default class MyComponent extends React.Component {
componentDidMount() {
AppDispatcher.dispatch({
type: ActionTypes.FETCH_DATA,
});
}
render() {
let isFetching = this.props.my.application.path.isFetching;
return (
My Component
);
}
}
Then in the store the FETCH_DATA triggers a request :
class AppStore extends ReduceStore {
//......
reduce(state, action) {
let imState = Immutable.fromJS(state);
switch (action.type) {
//......
case ActionTypes.FETCH_DATA:
doGetRequest('/url_to_service');
break;
//......
}
return imState.toJS();
}
}
The request would look something like this :
function doGetRequest(endpoint, params = {}) {
//request is some kind of AJAX library. In my case 'superagent'
request.get(endpoint)
.set('Accept','application/json')
.query(params)
.end(
(err, res) => {
if (res && res.ok) {
receiveData(endpoint, "SUCCESS", res);
} else {
receiveData(endpoint, "FAIL");
}});
}
Upon completion it would then dispatch another action.
function receiveData(endpoint, state, responseData) {
AppDispatcher.dispatch(
{
type: ActionTypes.SERVER_RESPONSE,
endpoint: endpoint,
state: state,
payload: responseData
}
);
}
Going back to the store, the second action is caught and the isFetching flag is set to false, then the application data is handled.
reduce(state, action) {
let imState = Immutable.fromJS(state);
switch (action.type) {
//......
case ActionTypes.SERVER_RESPONSE: {
imState = imState.setIn(['my','application','path', 'isFetching'], false)
if (action.state == "SUCCESS") {
//do something with the action.response data (via state update)
}else if (action.state == "FAIL") {
//maybe show an error message (via state update)
}
break;
}
}
return imState.toJS();
}
}
.... so this typical use case uses two 'actions', the first action being triggered from the componentDidMount method, and the second action is triggered after the request finishes.
Hope this pattern helps :)