一個實用的方法將存儲所有職位,並要求缺少的。假設你posts
減速是這樣的:
function posts(state = {}, action) {
switch (action.type) {
case "FETCH_ALL_POSTS":
return {...state, ...action.posts}
case "FETCH_POST":
return {...state, [action.post.id]: action.post}
default:
return state
}
}
你可以定義2個操作:
- 一個請求的所有帖子(可能包括分頁PARAMS)
- 一個請求單後
// Fetch all posts.
//
// In this example we are expecting the response to be like:
//
// {
// 12: {id: 12, title: "Hello", content: "..."},
// 16: {id: 16, title: "Bonjour", content: "..."},
// 54: {id: 54, title: "Hola", content: "..."},
// ...
// }
//
// If you want to return an array instead of a map the you need
// to normalize `posts`.
//
function fetchAllPosts() {
return dispatch => {
fetch("/api/posts")
.then(res => res.json())
.then(posts => dispatch({type: "FETCH_ALL_POSTS", posts}))
}
}
// Fetch a single post.
//
// Response would be:
//
// {id: 12, title: "Hello", content: "..."}
//
function fetchPost(id) {
return (dispatch, getState) => {
const state = getState()
// Check if the post is cached
if (state.posts[id]) {
dispatch({type: "FETCH_POST", post: state.posts[id]})
}
// Otherwise we must query the API
fetch(`/api/post/${id}`)
.then(res => res.json())
.then(post => dispatch({type: "FETCH_POST", post}))
}
}
然後在您的組件中(在安裝它們之前或路由之後),您可以調用上述操作來觸發加載。讓我們考慮你想顯示的帖子列表:
const PostList = connect(
state => ({
// Retrieve all posts as an array
posts: Object.values(state.posts),
}),
dispatch => ({
fetchAllPosts:() => dispatch(fetchAllPosts()),
})
)(
class PostList extends Component {
componentWillMount() {
// Load all posts if none were stored
if (this.props.posts.length === 0) {
this.props.fetchAllPosts()
}
}
render() {
return (
<ul>
{this.props.posts.map(
post => <PostItem key={post.id} id={post.id} />
)}
</ul>
)
}
}
)
const PostItem = connect(
(_, initialProps) => {
return state => ({
// Get the post data
post: state.posts[initialProps.id],
})
}
)(
class PostItem extends Component {
render() {
return (
<li>{this.props.post.title}</li>
)
}
}
)
Tada!簡單的情況下處理。現在,如果我們想顯示一個帖子,我們從商店中讀取它,或者獲取它。
const PostDetails = connect(
(_, initialProps) => {
// Read the post ID from the initial properties.
// We could imagine another case where the ID is read from the location.
const {id} = initialProps
return state => {
// May, or may not, return a post
post: state.posts[id],
}
},
(dispatch, initialProps) => {
// Same as above, we need to retrieve the post ID.
const {id} = initialProps
// Prepare an action creator to load THIS post.
const fetchThisPost =() => {
dispatch(fetchPost(id))
}
return() => ({
fetchThisPost,
})
}
)(
class PostDetails extends Component {
componentWillMount() {
// Load this post if it is not cached
if (!this.props.post) {
this.props.fetchThisPost()
}
}
render() {
if (!this.props.post) {
return <Loading />
} else {
return <PostCard />
}
}
}
)
對我來說這聽起來很合理。對'/ posts'的調用可能無法檢索到需要在'/ posts/1'中顯示的所有數據,因此您必須獲取剩餘的內容。在這種情況下,兩個減速器絕對有用。 – azium