I'm learning from the react-redux docs on middleware and have trouble understanding the purpose of the didInvalidate
property in the reddit example. It seems like the example goes through the middleware to let the store now the process of making an API call starting with INVALIDATE_SUBREDDIT
then to REQUEST_POSTS
then to RECEIVE_POSTS
. Why is the INVALIDATE_SUBREDDIT
necessary? Looking at the actions below, I can only guess that it prevents multiple fetches from happening in case the user clicks 'refresh' very rapidly. Is that the only purpose of this property?
function shouldFetchPosts(state, subreddit) {
const posts = state.postsBySubreddit[subreddit]
if (!posts) {
return true
} else if (posts.isFetching) {
return false
} else {
return posts.didInvalidate
}
}
export function fetchPostsIfNeeded(subreddit) {
return (dispatch, getState) => {
if (shouldFetchPosts(getState(), subreddit)) {
return dispatch(fetchPosts(subreddit))
}
}
}
I'm learning from the react-redux docs on middleware and have trouble understanding the purpose of the didInvalidate
property in the reddit example. It seems like the example goes through the middleware to let the store now the process of making an API call starting with INVALIDATE_SUBREDDIT
then to REQUEST_POSTS
then to RECEIVE_POSTS
. Why is the INVALIDATE_SUBREDDIT
necessary? Looking at the actions below, I can only guess that it prevents multiple fetches from happening in case the user clicks 'refresh' very rapidly. Is that the only purpose of this property?
function shouldFetchPosts(state, subreddit) {
const posts = state.postsBySubreddit[subreddit]
if (!posts) {
return true
} else if (posts.isFetching) {
return false
} else {
return posts.didInvalidate
}
}
export function fetchPostsIfNeeded(subreddit) {
return (dispatch, getState) => {
if (shouldFetchPosts(getState(), subreddit)) {
return dispatch(fetchPosts(subreddit))
}
}
}
Share
Improve this question
asked Aug 21, 2016 at 3:17
mangocaptainmangocaptain
1,4951 gold badge20 silver badges32 bronze badges
2 Answers
Reset to default 8You are close that didInvalidate
is related to reducing server requests, however it is kind of the opposite of preventing fetches. It informs the app it should go and fetch new data; the current data did 'invalidate'.
Knowing a bit about the lifecycle will help explain further. Redux uses mapStateToProps
to help to decide whether to redraw a Component when the global state changes.
When a Component is about to be redrawn, because the state (mapped to the props) changes for instance, ponentDidMount
is called. Typically if the state depends on remote data ponentDidMount
checks to see if the state contains a current representation of the remote data (e.g. via shouldFetchPosts
).
You are correct that it is inefficient to keep making the remote call but it is shouldFetchPosts
that guards against this. Once the required data has been fetched (!posts
is false) or it is in the process of being fetched (isFetching
is true) then the check shouldFetchPosts
returns false.
Once there is a set of posts
in the state then the app will never fetch another set from the server.
But what happens when the server side data changes? The app will typically provide a refresh button, which (as ponents should not change the state) issues an 'Action' (INVALIDATE_SUBREDDIT
for example) which is reduced into setting a flag (posts.didInvalidate
) in the state that indicates that the data is now invalid.
The change in state triggers the ponent redraw which, as mentioned, checks shouldFetchPosts
which falls into the clause that executes return posts.didInvalidate
which is now true, therefore firing the action to REQUEST_POSTS
and fetching the current server side data.
So to reiterate: didInvalidate
suggests a fetch of the current server side data is needed.
The most up-voted answer isn't entirely correct.
didInvalidate
is used to tell the app whether the data is stale or not. If true
, the data should be re-fetched from the server. If false
, we will use the data we already have.
In the official examples, firing INVALIDATE_SUBREDDIT
will set didInvalidate
to true. This Redux action can be dispatched as a result of a user action (clicking a refresh button), or something else (a countdown, a server push etc.)
However, firing INVALIDATE_SUBREDDIT
alone will not initiate a new request to the server. It is simply used to determine whether we should re-fetch the data or use the existing data when we call fetchPostsIfNeeded()
.
Because didInvalidate
is set to true
, the app will not let us fetch the data more than once. To refresh our data (e.g. after clicking a refresh button) we need to:
dispatch(invalidateSubreddit(selectedSubreddit))
dispatch(fetchPostsIfNeeded(selectedSubreddit))
Because we called invalidateSubreddit()
, didInvalidate
is set to true
and fetchPostsIfNeeded()
will initiate a re-fetch.
(This is why danmux's answer isn't entirely correct. The life cycle method ponentDidMount
will not be called when the state (which is mapped to the props) changes; ponentDidMount
is only called when the ponent mounts for the first time. So, the effect of hitting the refresh button will not appear until the ponent has been remounted, e.g. from a route change.)
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744229176a4564158.html
评论列表(0条)