建议分为以下三种情况:
(1)如果状态被0个组件依赖或者影响,那么我们认为这个状态不存在,放在redux中是没有用的
(2)如果这个状态只会被1个组件依赖或者影响。对于这种情况,其实如果你把这个状态放在这个组件内部,其它组件根本不会在乎。因为它们不需要,不需要改变它
(3)这个状态被多个组件依赖或者影响。这种情况会比上面两种情况复杂多了。你想象一下,如果我们按照情况 2解决方案来处理这种情况会发生什么问题。某个状态被某个组件所拥有,如果另外一个组件需要需要依赖或者影响这个状态的时候,就需要依赖那个组件
!举个例子,例如网站的按钮,点击它的时候需要发送 Ajax 请求并且 disabled 掉,并且弹出 loading modal。那么这个 loading 的状态不管放在按钮组件还是loading 组件都不合适,这样做必然会导致另外一个组件的依赖。一旦这种公共状态多起来,组件之间的依赖会极其混乱。
对于非扁平化的设计,我们可能会出现下面的代码:
const nick = getState().articles[0].comments[0].user.nick;
这种就是数据嵌套过深的情况,所以我们一般建议如下的非nosql的方式来减少存储数据的冗余,这就是所谓的范式化
的设计模式,每一个sub-state对应于一个关系型的数据库的表。如下就是扁平化的数据设计模式:
{
articles: [
{
id: 1,
title: 'React Intro',
content: 'about react'
},
{
id: 2,
title: 'Redux intro',
content: 'about redux'
}
],
users: [
{
id: 'morgan',
nick: 'Morgan'
}
],
comments: [
{
id: 1,
userId: 'user_1',
articleId: 1,
content: 'Good article'
}
]
}
详细查看这个知乎问答
如果没有redux,我们很可能遇到大量的ajax调用,然后setState的这种情况,此时我们的代码会非常冗余。而在纯react应用中解决大量的ajax请求的方式就是通过react-refetch来完成。我们先给出下面几个例子:
import React, { Component, PropTypes } from 'react'
import { connect, PromiseState } from 'react-refetch'
import PromiseStateContainer from './PromiseStateContainer'
export default class Profile extends Component {
render() {
const { userFetch, likesFetch } = this.props
return (
<PromiseStateContainer
ps={PromiseState.all([userFetch, likesFetch])}
//其中我们的ps就是调用PromiseState.all方法后返回的对象
onFulfillment={([user, likes]) => {
return (
<div>
<User user={user}/>
<Likes user={user} likes={likes}/>
</div>
)
}
}
/>
)
}
}
connect((props) => ({
userFetch: `/users/${props.userId}`,
likesFetch: `/users/${props.userId}/likes`
}))(Profile)
下面给出的就是我们的PromiseContainer的代码
import React, { Component, PropTypes } from 'react'
import { connect, PromiseState } from 'react-refetch'
import LoadingAnimation from './LoadingAnimation'
import ErrorBox from './ErrorBox'
class PromiseStateContainer extends Component {
static propTypes = {
ps: PropTypes.instanceOf(PromiseState).isRequired,
//必须是PromiseState实例对象
onPending: PropTypes.func,
onNoResults: PropTypes.func,
onRejection: PropTypes.func,
onFulfillment: PropTypes.func.isRequired,
}
static defaultProps = {
onPending: (meta) => <LoadingAnimation/>,
onNoResults: (value, meta) => <ErrorBox error="No results"/>,
onRejection: (reason, meta) => <ErrorBox error={reason}\/>,
}
render() {
const { ps, onPending, onNoResults, onRejection, onFulfillment } = this.props;
//获取我们的Promise.all返回的对象
if (ps.pending) {
return onPending(ps.meta)
} else if (ps.rejected) {
return onRejection(ps.reason, ps.meta)
} else if (ps.fulfilled && $.isEmptyObject(ps.value)) {
return onNoResults(ps.value, ps.meta)
} else if (ps.fulfilled) {
return onFulfillment(ps.value, ps.meta)
} else {
console.log('invalid promise state', ps)
return null
}
}
}
export default PromiseStateContainer
更多内容和配置请参考react-refetch
参考资料: