javascriptreactjsreact-sortable-hoc

React react-sortable-hoc cancel reordering(Undo order changes)


I'm using react-sortable-hoc to reorder table rows with Save and Cancel buttons. However, I can't find any information or example about reverting back to original order when the Cancel button is clicked after re-ordered rows.

Can't find any info or example on the official documentation or anywhere else. It seems weird to me that there's no cancel function built in or am I missing something?

Edit: Example code


Solution

  • If you want to undo order changes then you can maintain an undo stack. Each time an order change is complete, stash a copy of the previous data state. When the undo button is clicked you pop from the undo stack back into the data state.

    1. Add an undoStack to state.

      state = {
        data: range(1, 5).map((el) => ({
          name: `tester-${el}`,
          age: el,
          class: `Class-${el}`
        })),
        undoStack: [],
      };
      
    2. Cache the previous data state in the undo stack. Here I'm using slice to keep only the last 10 revisions, but this can be tuned to fit your needs.

      _handleSort = ({ oldIndex, newIndex }) => {
        this.setState((prevState) => ({
          data: arrayMove(prevState.data, oldIndex, newIndex),
          undoStack: [...prevState.undoStack, prevState.data].slice(-10),
        }));
      };
      
    3. Handle undoing order changes and attach the undo handler to the button's onClick event handler.

      undo = () => {
        this.setState(prevState => {
          if (prevState.undoStack.length) {
            return {
              data: prevState.undoStack.pop(),
              undoStack: prevState.undoStack,
            };
          } else {
            return prevState;
          }
        })
      };
      
      ...
      
      <button type="button" onClick={this.undo}>
        Undo reorder
      </button>
      

    Demo

    Edit react-react-sortable-hoc-cancel-reorderingundo-order-changes

    If you don't care about intermediate revisions and simply want to reset to the original order then just capture a cache of the original order and reset data.

    const data = range(1, 5).map((el) => ({
      name: `tester-${el}`,
      age: el,
      class: `Class-${el}`
    }));
    
    class App extends React.Component {
      state = {
        data,
        originalData: data, // <-- store cache of original data
        undoStack: []
      };
    
      ...
    
      <button
        type="button"
        onClick={() => {
          this.setState({
            data: this.state.originalData // <-- restore from cache
          });
        }}
      >
        Reset
      </button>
    

    Both are implemented in the linked codesandbox.