SortableJS / react-sortablejs

React bindings for SortableJS
http://sortablejs.github.io/react-sortablejs/
MIT License
2.07k stars 211 forks source link

[bug] List Prop Edited by Reference #294

Open amans199 opened 1 month ago

amans199 commented 1 month ago

Describe the bug The list prop in the ReactSortable component is being modified by reference. This leads to unexpected behavior when the items in the list are altered, as the original list passed as a prop gets affected.

To Reproduce Steps to reproduce the behavior:

  1. Use the ReactSortable component with a list prop that contains objects that do not have the chosen or selected keys.
  2. Perform an action that modifies the state of an item in the list (e.g., selecting or deselecting an item).
  3. Observe that the chosen and selected keys are added to the objects in the original list prop.
  4. If the original list items do not use these keys, it leads to an unintended modification of the list structure and potential bugs in the application.

Expected behavior The original list prop should remain unchanged when the state of the items is modified. A deep copy of the list should be used to ensure that the items are independent of the original list.

Information When you use it like this

  <ReactSortable
        className='d-flex flex-column gap-4'
        list={originalList} // this changes the originalList
        // list={JSON.parse(JSON.stringify(originalList))}  // first fix 
        // list={originalList.map((item) => ({ ...item }))} // second fix 
        setList={handleSettingList}
        onStart={handleStartDragging}
        onEnd={handleEndDragging}
      >
</ReactSortable>

In the code of the package in the file react-sortable.tsx in line 52 there is this code below which apparently makes a shallow copy of the list; hence this problem happen.

    const newList = [...props.list].map((item) =>
      Object.assign({}, item, {
        chosen: false,
        selected: false,
      })
    );

I suggest changing that part [...props.list] to make a deep copy.

Versions - Look in your package.json for this information: "react-sortablejs": "^6.1.4" "react": "^18.2.0"

Additional context Using JSON.parse(JSON.stringify(...)) or a library like Lodash's _.cloneDeep can resolve the issue by ensuring that a deep copy of the list is created before any modifications are made. This way, the original list prop remains intact.