我面临的情况是我将一系列作业存储为Redux状态 . 我有一个容器,它使用Redux connect访问数据并使用this.props.params中的参数然后找到适当的Job,然后将其作为prop传递给它的子项 .
在子组件中,作业会触发更新作业的操作,然后合并并更新存储中的作业 . 这似乎工作正常,但当容器重新渲染时,孩子没有 . 我可以看到,这与我不把工作存放为道具或国家这一事实有关 .
我的问题是什么是最好的(Redux)方法来处理这个问题?
因此,如果我将JobShow更改为包含jobs = ,则会在作业更新后重新呈现 . 这似乎表明状态没有变异,我也可以确认容器本身重新渲染甚至重新运行renderView()但不重新渲染JobShow .
容器:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import * as actions from '../../actions';
import JobShow from './job_show';
class JobContainer extends Component {
constructor(props){
super(props);
}
renderView(job, customer){
let viewParam = this.props.params.view;
switch(viewParam){
case "edit": return <JobEdit customer={customer} job={job}/>
case "notes": return <JobShow customer={customer} activeTab={"notes"} job={job}/>
case "quote": return <JobShow customer={customer} activeTab={"quote"} job={job}/>
case "invoice": return <JobShow customer={customer} activeTab={"invoice"} job={job}/>
default: return <JobShow customer={customer} activeTab={"notes"} job={job}/>
}
}
render() {
let { jobs, customers } = this.props;
if (jobs.length < 1 || customers.length < 1){
return <div>Loading...</div>;
}
let job = jobs.find(jobbie => jobbie.displayId == this.props.params.jobId);
let customer = customers.find(customer => customer._id.$oid == job.customers[0]);
return (
<div className="rhs">
{this.renderView(job, customer)}
</div>
);
}
}
JobContainer.contextTypes = {
router: React.PropTypes.object.isRequired
};
function mapStateToProps(state) {
return {
jobs: state.jobs.all,
customers: state.customers.all
};
}
export default connect(mapStateToProps, actions )(JobContainer);
Reducer片段:
import update from 'react-addons-update';
import _ from 'lodash';
export default function(state= INITIAL_STATE, action) {
switch (action.type) {
case FETCH_ALL_JOBS:
return { ...state, all: action.payload, fetched: true };
case UPDATE_JOB_STATUS:
let newStatusdata = action.payload;
let jobToUpdate = state.all.find(jobbie => jobbie.displayId == newStatusdata.displayId);
jobToUpdate.status = newStatusdata.newStatus;
jobToUpdate.modifiedAt = newStatusdata.timeModified;
let updatedJobIndex = _.indexOf(state.all, state.all.find(jobbie => jobbie.displayId == newStatusdata.displayId));
let updatedState = update(state.all, {$merge: {[updatedJobIndex]: jobToUpdate}});
return { ...state, all: updatedState}
2 回答
看起来你自己想出来了,但你可能会发现轻微的重构可以提高你所做的事情的清晰度 . 以下是如何使用对象分配操作更改Reducer结构的一些示例:
来自:https://github.com/mjw56/redux/blob/a8daa288d2beeefefcb88c577a7c0a86b0eb8340/examples/todomvc/reducers/todos.js
官方redux文档中还有更多内容(redux.js.org/docs/recipes/UsingObjectSpreadOperator.html)
您也可能会发现编写测试并使用像deepFreeze这样的软件包很有用,因为如果您意外地改变状态而没有意识到,它会告诉您抛出错误 .
@markerikson在评论中指出的问题是我正在改变状态 . 使用react-addons-update中的$ set函数,我成功更新了内容 .
新的reducer片段如下所示: