2016-10-18 3 views
2

내 React 기반 프로젝트 (React Boilerplate에 빌드 됨)에 Redux와 Immutable.js를 사용하고 있으며, 변경하거나 변경 불가능한 것을 추가하는 관용적 인 방법을 찾고 있습니다. js 목록.immutable.js를 업데이트하거나 추가하는 방법

현재 설정. 국가는 처음에 다음과 같습니다

const initialState = fromJS({ 
    accounts: [], 
    activeAccount: null, 
    loadedAccounts: [], 
}); 

내가 account 개체에 대한 불변의 기록이 있습니다

const account = new Record({ 
    description: '', 
    id: '', 
    name: '', 
    status: '', 
}); 

그리고 내 감속기 :

function reducer(state = initialState, action) { 
    switch (action.type) { 
    case LOAD_ACCOUNT_SUCCESS: 
     return state 
     .set('activeAccount', new account(action.account)) 
    default: 
     return state; 
    } 
} 

이 잘 작동 - LOAD_ACCOUNT_SUCCESS 조치가있을 때 해고되면 activeAccountaction.account의 값으로 업데이트됩니다.

function reducer(state = initialState, action) { 
    switch (action.type) { 
    case LOAD_ACCOUNT_SUCCESS: 
     const loadedAccount = new account(action.account); 
     return state 
      .update('loadedAccounts', (loadedAccounts) => loadedAccounts.push(loadedAccount)); 
    default: 
     return state; 
    } 
} 

을하지만, 새로운 레코드가 발생합니다 두 번 같은 계정 데이터를로드하는 순간에 밀려 : 모든 새로운 LOAD_ACCOUNT_SUCCESS 작업을 대신 loadedAccounts에 새로로드 된 계정 데이터를 밀어 수 있도록

나는 이것을 수정할 수 있습니다 매번 내 목록에 올리십시오 (데이터 복제). 지금 내가 원하는 것은 입니다.action.accountloadedAccounts에 추가하십시오 (일치하는 ID가있는 경우) 또는 목록의 레코드를 업데이트하십시오. 나는 유사한 질문과 슬픔에 잠긴 Immutable.js 문서를보고 있는데 어떻게 해야할지 모르겠다. 내가 기대했던대로 구문을 사용하지 않았다.

답변

2

에 액세스 할 수있는 업데이트 방법 또한, 내가로 교체 할 객체를 전달하고 있지 않다, 그러나 당신은 또한 기존 개체를 전달할 수 있습니다, 당신이 무엇을 할 여기서 필요한 것은 중첩 된 업데이트입니다. 처음에는이 계정이 있는지 여부에 관계없이 loadedAccounts 목록을 확인해야합니다. 두 번째로 activeAccount 필드를 변경해야합니다. 그리고 마지막으로 loadedAccounts에 계정을 추가 (또는 업데이트)하십시오.

여기서주의해야 할 점은 account 속성을 전달하는 방법입니다. 당신이 어딘가에서 그것을 파생하고 주위에 Record 전달할 경우 그냥 === (또는. equals()) 의해 비교할 수 있지만 그냥 일반 자바 스크립트 개체를 것 - 나중에 가정 해 봅니다.

같은 뭔가가 될 코드의 관점에서 :

// we can do it by different ways, it is just one of them 
const listWithLoadedAccounts = state.get('loadedAccounts'); 
const isAccountAlready = Boolean(
    listWithLoadedAccounts.filter(
    account => account.get('id') === action.account.id 
).size 
); 

const patchedState = state.set('activeAccount', action.account.id); 
return isAccountAlready 
    ? patchedState.updateIn(['loadedAccounts'], list => list.map(account => account.get('id') === account.action.id ? new account(action.account) : account)) 
    : patchedState.updateIn(['loadedAccounts'], list => list.concat(new account(action.account))) 

이상적인 코드는 무엇인가는 중복 제거 할 수있는 것이 아니라, 당신은 아이디어를 얻을 - 당신은 변경해야하는 경우 항상 완전 병합/업데이트를 사용 중첩 필드 또는 데이터 구조.

당신은 또한 같은 직접 새 필드를 설정할 수 있습니다

const oldList = state.get('loadedAccounts'); 
const newList = oldList.concat(action.account); 
const patchedState = state.set('loadedAccounts', newList); 

하지만 완전 병합을 수행 할 수있는 매우 일반적인 작업이기 때문에 나는 개인적으로,이 일치하지 또한 유연하고되지는 사실을 알게 될 것입니다.

+0

감사합니다. 잘못 입력하여 업데이트/추가 (사용자의 3 자 검사를 피하는)보다 우아한 방법이 있다고 가정했는데, 분명히 장점이 있다고 생각합니다. – CherryFlavourPez

0

이 예제가 도움이되기를 바랍니다. 새로운 불변 ​​목록을 만들고 첫 번째 업데이트를 수행 한 다음 새 요소를 추가하려고합니다. 당신이 그래서 현재 항목

class Test { 
 
    a = null; 
 
    b = null; 
 
constructor(a,b){ 
 
this.a=a; 
 
this.b=b; 
 
} 
 
} 
 

 
$("#test").html(""); 
 

 
function logme(item){ 
 
    $("#test").append("<br/>"+JSON.stringify(item)); 
 
} 
 
function logmeNewLine(){ 
 
    $("#test").append("<br/>"); 
 
} 
 

 
function listAddUpadte(key){ 
 
    
 
    var index= list.get('data').findIndex(listing => { 
 
    return listing.a === key; 
 
    }); 
 
    
 
    logme(' found index (-1 for not found) : ' + index); 
 
    
 
    if(index >= 0){ 
 
    logme("upadte"); 
 
    list = list.set("data",list.get("data").update(index,function(item){ 
 
    return new Test(key,"go"); 
 
    })); 
 
    }else { 
 
    
 
    logme("add"); 
 
    list = list.set("data",list.get("data").push(new Test(key,"go"))); 
 
    } 
 

 
    list.get('data').forEach(item=>{ 
 
    logme(item); 
 
    }); 
 
} 
 

 

 
var list = Immutable.fromJS({ 
 
"data":[new Test(6,"abhi"),new Test(4,"raj"),new Test(1,"ajay")] 
 
}); 
 

 
logme("intial data"); 
 
list.get('data').forEach(item=>{ 
 
    
 
logme(item); 
 
    
 
}); 
 

 

 

 

 
logmeNewLine(); 
 
logme("testing replace with a = 4 ") 
 
logmeNewLine(); 
 
listAddUpadte(4); 
 

 

 
logmeNewLine(); 
 
logme("testing add with a = 8 ") 
 
logmeNewLine(); 
 
listAddUpadte(8); 
 
logmeNewLine(); 
 
logmeNewLine(); 
 
logmeNewLine();
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.7.2/immutable.min.js"></script> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div id="test"></div>

관련 문제