React event not dispatching actions to the store

Viewed 168

I'm working on a project that involves drag and drop with React/Redux.

const InitialState = {

  dragged: 0,
  entered: 0,
  
}

my reducer:

export const formReducer = (state = InitialState, action = {}) => {
  console.log(action)
  switch (action.type) {
   
    case types.DRAGGED_ITEM:
      return {
        ...state,
        dragged: action.payload
      }

    case types.ENTERED_ITEM:
      return {
        ...state,
        entered: action.payload
      }
    case types.DRAGGED_END:
      return {
        ...state,
        createdElements: reArrangeElements(state.createdElements, state.dragged, state.entered)
      }

    
    default:
      return state;
  }
}

reArrangeElement function:

const reArrangeElements = (elArray, start, enter) => {
  const newArr = [...elArray];
  const draggedItem = newArr[start];
  const enteredItem = newArr[enter];
  newArr.splice(start, 1, enteredItem);
  newArr.splice(enter, 1, draggedItem);
  return newArr;
}

My actions:

export const draggedItem = (position) => ({
  type: types.DRAGGED_ITEM,
  payload: position
})

export const enteredItem = (position) => ({
  type: types.ENTERED_ITEM,
  payload: position
})

export const dragEnd = () => ({
  type: types.DRAGGED_END
})

And my Form Builder Function: And this is where the problem is, am passing down to the function the actions I want to be dispatched to the store, but the event don't work well especially the onDragStart event, when I pass the action to it, it disables the draggable, and onDragEnter won't trigger. When I disable the action am passing to onDragStart the element becomes draggable. Before now, it work fine, but I don't know what happened, what am I missing?

_creator function is just invoking and returning React.createElement()

const _formBuilder = (newComponents, index, remove, draggedItem, enteredItem, dragEnd) => {

  if (!newComponents.length) return;


  const divContainer = _creator('div', {
    key: Math.floor(Math.random() * 1000),
    draggable: true,
    onDragStart: (e) => {

      console.log(index)
      return draggedItem(index)
    },
    onDragEnter: (e) => {
      console.log(index)
      return enteredItem(index)
    },
    onDragEnd: (e) => {
      console.log('index')
      return dragEnd()
    },
   
  }, [
    newElement,
    trash,
  ]);

  return divContainer;
};
2 Answers

From what I understood, the final render element was not considering the updated order - you update the state in entered, but it was not used anywhere. I made a very rough change, just to accommodate only two elements, but I guess you can elaborate from here.

Also another important thing — is a fixed key for every element - this is crucial for React rendering. I guess that was the cause why onDragEnter was not triggering.

Here is a reworked sandbox.

I have fixed your sandbox error. By changing key: Math.floor(Math.random() * 1000), to key: index

The reason behind this is every time you dispatch action react will try to rerender it. Since you generate key randomly every time, react will consider it as a different component.

So after you dispatch an action on drag start, Your original component will disappear and a new complete new one will appear there. That's why drag is canceled.

So keeping component's key as unique and unchanged is important. You kept it unique but it did change over time.

https://codesandbox.io/s/ecstatic-yalow-xt1cb?file=/src/App.js

Related