一个实用的方法将存储所有职位,并要求缺少的。假设你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