2016-06-27 7 views
1

내가 직면하고있는 시나리오는 Redux 상태로 저장된 작업 배열이 있다는 것입니다. Redux를 사용하여 데이터에 액세스하는 컨테이너가 있고 this.props.params의 매개 변수를 사용하여 적절한 작업을 찾은 다음 자식을 소품으로 넘깁니다.React, 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); 

감속기 발췌문 :

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} 
+0

그 밖의 것이 없다면'jobToUpdate.status = ....'라는 줄로 상태를 바꾼 것처럼 보입니다. 우발적 돌연변이는 거의 항상 구성 요소가 다시 렌더링되지 않는 이유입니다. http://redux.js.org/docs/FAQ.html#react-not-rerendering을 참조하십시오. 또한, 직업과 초기 상태는 어떻게 생겼습니까? – markerikson

+0

그래서 JobShow를 jobs = {jobs}를 포함하도록 변경하면 작업이 업데이트되었지만 소품을 전달할 때 자식이 필요하지 않는 것은 잘못된 방법 인 것처럼 보입니다. 이것은 상태가 변하지 않고 컨테이너 자체가 renderView 함수를 다시 렌더링하고 다시 실행하지만 JobShow를 다시 렌더링하지 않는다는 것을 확인할 수 있습니다. –

+0

더 많은 코드를 보는 것이 도움이 될 수 있지만 감속기 스 니펫의'jobToUpdate' 줄은 복사본 만들기, 복사본 수정 및 그 복사본 반환하기보다는 해당 작업 개체를 직접 변형시키는 것입니다. 그래서 네, 그 작업 객체 자체를 하위 구성 요소에 소품으로 전달하려고하면 참조 자체가 변경되지 않고 하위 구성 요소가 업데이트되지 않습니다. – markerikson

답변

1

문제로 I 상태가 돌연변이 된 것이 었습니다 @markerikson에 의해 코멘트 지적했다. react-addons-update의 $ set 함수를 사용하여 내용을 성공적으로 업데이트했습니다. 당신이 자신을 그것을 생각처럼

case UPDATE_JOB_STATUS: 

    let newStatusdata = action.payload; 

    let jobToUpdate = state.all.find(jobbie => jobbie.displayId == newStatusdata.displayId); 
    let updatedJob = update(jobToUpdate, {status:{$set: newStatusdata.newStatus}}) 
    updatedJob = update(updatedJob, {modifiedAt:{$set: newStatusdata.timeModified}}) 

    let updatedJobIndex = _.indexOf(state.all, state.all.find(jobbie => jobbie.displayId == newStatusdata.displayId)); 
    let updatedState = update(state.all, {$merge: {[updatedJobIndex]: updatedJob}}); 

    return { ...state, all: updatedState} 
1

이 보이는,하지만 당신은 약간의 리팩토링 당신이 무슨 일을하는지의 선명도를 향상 찾을 수 있습니다 :

새로운 감속기 조각은 다음과 같습니다. 에서

case ActionTypes.EDIT_TODO: 
    return Object.assign({}, 
    state, 
    { text: action.text } 
) 

: https://github.com/mjw56/redux/blob/a8daa288d2beeefefcb88c577a7c0a86b0eb8340/examples/todomvc/reducers/todos.js

뿐만 아니라 공식 REDUX 문서 더있다 (redux.js.org/ 다음은 객체 할당 작업을 사용하여 감속기의 구조를 변경하는 방법의 몇 가지 예입니다 doc30/recipe/UsingObjectSpreadOperator.html)

실수로 상태를 변경하지 않고 오류가 발생하면 테스트를 작성하고 deepFreeze과 같은 패키지를 사용하면 유용합니다.

관련 문제