2017-11-16 3 views
0

ドラッグでDropを使用してdivのReact/Reduxを再配置しようとしていますが、私は説明できない奇妙な振る舞いがあります。私は次の減速器を持っています。(可読性のための縮小版)変更する前にconsole.logが変更された状態を表示します

コード中央付近に5つの "console.log"があります。 の状態またはの構造体を記録すると、クロムコンソールはすでに並べ替えられたバージョンを印刷します。どうして?

export default function reducer(
    state={ 
     structures: [], 
     elementUniqueCounter: 0, 
     hoveredElement: null, 
     DnD: { 
      dragContent: null, 
      dragOverContent: null, 
      dragContentTop: true, 
      dragStructure: null, 
      dragOverStructure: null, 
      dragStructureTop: true, 
      content: null, 
      mousepositon: {} 
     } 
    }, action) { 
    let DnD = Object.assign({}, state.DnD); 
    let structs = state.structures.slice(); 
    switch (action.type) { 
     case "STOP_DRAG_CONTENT": 
      let cindex_source; 
      let index_source; 
      let cindex_target; 
      let index_target; 
      let foundTarget = false; 
      let foundSource = false; 

      structs.map(function (struct, index) { 
       struct.content.map(function (content, cindex) { 
        if(content.id === DnD.dragOverContent.props.id) { 
         cindex_target = cindex; 
         index_target = index; 
         foundTarget = true; 
        } 
        if(content.id === DnD.dragContent.props.id) { 
         cindex_source = cindex; 
         index_source = index; 
         foundSource = true; 
        } 
       }); 
      }); 
      console.log(state); 
      console.log(index_source); 
      console.log(cindex_source); 
      console.log(index_target); 
      console.log(cindex_target); 
      if(index_source !== undefined && cindex_source !== undefined && index_target !== undefined && cindex_target !== undefined) { 
       let copy = structs[index_source].content.slice(cindex_source, cindex_source+1)[0]; 
       copy.content = DnD.content; 
       structs[index_source].content.splice(cindex_source, 1); 
       if (DnD.dragContentTop) { 
        structs[index_target].content.splice(cindex_target+1, 0, copy); 
       } else { 
        structs[index_target].content.splice(cindex_target, 0, copy); 
       } 
      } 

      DnD = { 
       dragContent: null, 
       dragOverContent: null, 
       dragContentTop: true, 
       dragStructure: null, 
       dragOverStructure: null, 
       dragStructureTop: true, 
       content: null, 
       mousepositon: {} 
      }; 
      return {...state, DnD: DnD, structures: structs}; 

    } 

    return state 
} 

答えて

1

再配置されたバージョンが発生する前に印刷されているわけではありません。それはあなたが変異しているオブジェクトを印刷していることです。コンソール上のオブジェクトを見るときには、突然変異がすでに発生しています。

の使用が変異している。

structs[index_source].content.splice(cindex_source, 1); 
if (DnD.dragContentTop) { 
    structs[index_target].content.splice(cindex_target+1, 0, copy); 
} else { 
    structs[index_target].content.splice(cindex_target, 0, copy); 
} 

EDIT:

上記の変異が実際にstate.structuresのネストされたプロパティを変異されます。これは、.slice()が元のオブジェクトの浅いコピーを返すために起こります。

slice()メソッドは、配列の一部のシャローコピーを、beginからend(endは含まない)から選択した新しい配列オブジェクトに返します。元の配列は変更されません。

シャローコピーのオブジェクトは、state.structuresのオブジェクトへのポインタに過ぎません。したがって、.splice()を使用すると、それらの参照された値が変更されます。

これを説明するスニペットを示します。それを見てconsole.logを見てください。

const people = [ 
 
\t { 
 
\t \t name: "Joe", 
 
\t \t age: "52" 
 
\t }, 
 
\t { 
 
\t \t name: "Sally", 
 
\t \t age: "48" 
 
\t } 
 

 
]; 
 

 
const clonedPeople = people.slice(); 
 

 
console.log("people === clonedPeople: ", people === clonedPeople); 
 
console.log("people[0] === clonedPeople[0]: ", people[0] === clonedPeople[0]); 
 

 
const deeplyClonedPeople = JSON.parse(JSON.stringify(people)); 
 

 
console.log("people[0] === deeplyClonedPeople[0]: ", people[0] === deeplyClonedPeople[0]);

この情報がお役に立てば幸い!

+0

私はスライスでコピー(参照ではない)を作ることができると思いました。だから私はスイッチの前にそれを使ったのです(structs = state.structures.slice();) – Tiega

+0

はい、 'slice'は' shallow'コピーを返すだけで、ネストされたプロパティを変更しています。 'slice'を使う代わりに' JSON.parse(JSON.stringify(state.structures)) 'でオブジェクトを複製してみてください。このメソッドは結果のオブジェクトから 'undefined'値を削除することに注意してください。 –

+0

私は、ネストされたプロパティが問題であることを知りませんでした。ありがとう – Tiega

関連する問題