0

My purpose to implement dragging elements from one list to another, example:

  1. Dragging layout2 element (has 2 nested blocks) into editor.
  2. Dragging paragraph into the one of two layout blocks.

The issue that I faced up is the layout block doesn’t save any element inside itself. When dragging layout block into Editor is everything okey but if dragging paragraph into layout block, as I expected its appear there is but its not.

Please check the link with source code: https://stackblitz.com/edit/stackblitz-starters-dwd2dm?file=src%2FApp.tsx

1 Answer 1

1

One possible reason for this behavior could be related to how you're updating the state when dropping elements into the layout block. In the Layout6 component, when you're updating the state after dropping elements into the layout block, you're concatenating the new list with the existing content:

setList={(newList) => {
  const updatedState = layoutState.map((item) =>
    item.id === sortable.id ? { ...item, content: [...item.content, ...newList] } : item,
  );
  setLayoutState(updatedState);
}}

Instead of directly concatenating the lists ([...item.content, ...newList]), try setting the content directly to the new list:

setList={(newList) => {
  const updatedState = layoutState.map((item) =>
    item.id === sortable.id ? { ...item, content: newList } : item,
  );
  setLayoutState(updatedState);
}}

By doing this, the content of the layout block will be replaced by the dropped elements rather than appended to the existing content.

I tried replacing L98 - L104 with my code, and I feel it works as it doesn't repeat/misinterprete dragged components into layout.

Appended

Replace Layout2 and Layout6 with the following code to check if it works. I tried replacing them with this code, and now drag to Layout2 and Layout6 work fine.

const Layout2 = () => {
  const { layoutState, setLayoutState } = useContext(MyContext);
  return (
    <div style={{ display: 'flex' }}>
      {layoutState[0]?.child.map((layoutItem, idx) => (
        <ReactSortable
          key={layoutItem.id}
          group={{
            name: 'layout-item',
            pull: true,
            put: ['orthography-list', 'editor-list'],
          }}
          animation={150}
          list={layoutItem.context}
          setList={(newList) => {
            const updatedState = [...layoutState];
            updatedState[0].child[idx].context = newList;
            setLayoutState(updatedState);
          }}
          style={{
            border: '1px solid blue',
            margin: 10,
            minHeight: 50,
            width: layoutItem.width[idx],
          }}
          className="layout-container"
        >
          {layoutItem.context?.map((item, idx) => (
            <div
              key={`${item.id}`}
              data-id={`${item.id}`}
              className="layout-content"
            >
              {item.content}
            </div>
          ))}
        </ReactSortable>
      ))}
    </div>
  );
};

const Layout6 = () => {
  const { layoutState, setLayoutState } = useContext(MyContext);

  return (
    <ReactSortable
      list={layoutState[1].child}
      setList={(newList) => {
        const updatedState = [...layoutState];
        updatedState[1].child = newList;
        setLayoutState(updatedState);
      }}
      group={{
        name: 'layout-6',
        pull: true,
        put: [],
      }}
      animation={150}
      style={{
        border: '1px solid skyblue',
        margin: 10,
        minHeight: 50,
        minWidth: 50,
        display: 'flex',
        flexDirection: 'row',
      }}
      className="layout-block"
    >
      {layoutState[1].child.map((sortable) => (
        <ReactSortable
          key={sortable.id}
          data-id={sortable.id}
          group={{
            name: 'layout-item',
            pull: true,
            put: ['orthography-list', 'editor-list'],
          }}
          animation={150}
          list={sortable.context}
          setList={(newList) => {
            const updatedState = [...layoutState];
            updatedState[1].child = updatedState[1].child.map((item) =>
              item.id === sortable.id ? { ...item, context: newList } : item
            );
            setLayoutState(updatedState);
          }}
          style={{
            border: '1px solid blue',
            margin: 10,
            minHeight: 50,
            minWidth: 50,
          }}
          className="layout-container"
        >
          {sortable.context.map((item, idx) => (
            <div
              key={`${item.id}-${idx}`}
              data-id={`${item.id}-${idx}`}
              className="layout-content"
            >
              {item.content}
            </div>
          ))}
        </ReactSortable>
      ))}
    </ReactSortable>
  );
};
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks you for answer. I will appreciate if you provide code, cos little bit misunderstood part where you are compare item.id === sortable.id, cos item.id has layout-2-0 format and sortable.id has l-2-0 format
Thank you for provided code. I encountered with strange behave when first time drag layout6 in the editor then fill at least one block, then the second time drag layout6 as the result it is already has content of first. Expected result each block has own content.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.