私が直面しているシナリオは、Redux状態として格納されている一連のジョブがあることです。 Reduxでデータにアクセスするコンテナがあり、this.props.paramsのパラメータを使用して適切なJobを見つけ、その子を小道具にします。React、Redux:状態の更新と子の再レンダリング
子コンポーネント内では、ジョブによってジョブが更新され、マージされ、ストア内のジョブが更新されます。これは正常に動作しているようですが、コンテナが子を再レンダリングするときには表示されません。私はそれが私が小道具や状態として仕事を保存しないという事実と関係があることがわかります。
私の質問は、これを処理するための最良の(Redux)方法は何ですか?
したがって、JobShowにjobs = {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);
リデューサースニペット:@markeriksonによるコメントで指摘したように
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}
それ以外の場合は、あなたの状態を 'jobToUpdate.status = ....'という行で変更しているようです。誤った突然変異は、ほとんどの場合、コンポーネントが再レンダリングしない理由です。 http://redux.js.org/docs/FAQ.html#react-not-rerenderingを参照してください。また、仕事とあなたの最初の状態はどのように見えるのですか? – markerikson
ジョブをジョブに含めるようにJobShowを変更した場合、{ジョブ}は、ジョブが更新されたときにレンダリングされますが、必要な子プロセスは間違っているようです。これは状態が変化していないことを示しているようですが、コンテナ自体がrenderView関数を再レンダリングして再実行しても、JobShowを再レンダリングしないことも確認できます。 –
もっと多くのコードを見ると助けになるかもしれませんが、レジューサースニペットの 'jobToUpdate'行は、コピーを作成するのではなく、コピーを修正してそのコピーを返すのではなく、したがって、そのジョブオブジェクト自体を子コンポーネントに小道具として渡そうとすると、参照自体は変更されず、子コンポーネントは更新されません。 – markerikson