我们说我有一个REST API来编辑用户个人资料。 这里有两种方法
当然,当用户更新他的个人资料时,我想获取完成分数。
以下是我的(天真?)方式,redux
和redux-thunk
动作创建者
function updateProfileAction(userId, profile) {
return function (dispatch) {
dispatch("PROFILE_UPDATE", /*...*/)
api.updateProfile(userId, profile)
.then(repsonse => dispatch("PROFILE_UPDATE_SUCCESS", /*...*/))
// ▼ triggers the action that fetch the completion score
// this is the line that bugs me
.then(() => fetchProfileCompletionAction(userId))
}
}
这条线路让我感到困惑:
udpateProfileAction
突然负责取得完成权); 例如,如果由于某种原因,我不想再显示完成情况(比如我删除显示它的组件)并忘记删除这行代码,fetchCompletion
将是触发但永远不会在图形组件中使用。)
我在考虑,也许在消耗完成的组件中,我可以订阅商店,此时dispatch
。这将允许我以更具反应性的方式
function Completion(props) {
props.store.subscribe(state => {
//check if profile has changed
dispatch(fetchProfileCompletionAction(userId))
})
return <div> {props.completion} </div>
}
这是个好主意吗?有一个更好的方法吗?此外,我想检查相关状态已经发生变化对于这个解决方案来说并不是真的微不足道。
答案 0 :(得分:3)
就个人而言,我更喜欢你目前的解决方案。
我想起来就像这样:
有了这个理念,如果提出一个额外的行动,没有减速器正在寻找,那么无关紧要。如果某些状态发生变化,没有任何组件会呈现,那么无关紧要。
根据你的建议,根据你的第二个建议,很难确定状态是否已经改变,因为你只有当前状态而没有以前的状态来确定。
如果您确实想要这样做,可以使用componentWillReceiveProps
并使用react-redux连接组件,以便状态更改通过props进行,例如:
class ProfileSuccessNotification extends React.Component {
componentWillReceiveProps(nextProps) {
if (!this.props.success && nextProps.success) {
this.props.showNotification(nextProps.userId)
}
}
render() {
return this.props.show ? <p>{this.props.userId} fetched successfully!</p> : null
}
}
// map from where ever in your state
const mapStateToProps = (state) => ({
userId: state.profile.userId,
success: state.profile.loaded,
show: state.profileNotification.show
})
const mapDispatchToProps = (dispatch) => ({
showNotification: (userId) => dispatch(fetchProfileCompletionAction(userId))
})
export default connect(mapStateToProps, mapDispatchToProps)(ProfileSuccessNotification)
当然,您也可以让多个Reducer对同一个动作做出反应。我不确定PROFILE_UPDATE_SUCCESS
和fetchProfileCompletionAction
引发的操作之间的区别是什么,所以也许你只想在PROFILE_UPDATE_SUCCESS
被提升时更新2个状态,根本不需要连接第二个动作。
答案 1 :(得分:2)
经过几次测试后,我尝试redux-cycles
作为redux-thunk
的替代品,它可以很好地处理这类问题。
它允许我订阅要更改的配置文件,并在更新配置文件时请求完成服务器的完成。哪个方式在语义上更正确比我在初始问题中所做的那样。
这是代码的样子
function main(sources) {
const updateProfileRequest = sources.ACTION
.filter(action => action.type === "UPDATE_PROFILE")
.map(action => ({ /* update profile request object */))
const profileUpdateSuccess$ = sources.HTTP
.select("profileUpdate")
.flatten()
// when a profile request is successful, I want to warn the store
.map(response => ({ type: "UPDATE_PROFILE_SUCCESS", profile: response.body })
const fetchCompletionRequest$ = sources.STATE
.map(state => state.profile)
// whenever the state changes, I want to fetch the completion
.compose(dropRepeats())
.mapTo({ /* fetch profile request object */ })
return {
HTTP: xs.merge(udpateProfileRequest$, fetchCompletionRequest$),
ACTION: profileUpdateSuccess$
}
}
redux-thunk
在我的第一次尝试中,代码的语义是:
当用户请求更新其个人资料时:当响应到达时,将更新请求发送到服务器 AND ,发送profile_update_success
AND 发送请求以获取新的完成值
这是单个组件的责任。
redux-cycles
现在,redux-cycles
这就是我的代码的含义:
当用户请求更新其个人资料时:将更新请求发送到服务器
更新个人资料回复到达时:发送UPDATE_PROFILE_SUCCESS
操作
更新商店的个人资料:发送请求以获得新的完成
这三个动作完全分离,并且具有单独的语义。
注意第二步是&#34;当 更新配置文件响应到达时#34;而不是&#34;当 更新个人资料回复&#34; :)
所以最后,我没有解决非分形问题,但我认为这是redux
的本质,所以我无能为力,但至少我有一个更强大的反应系统。