ReactSortable 渲染嵌套组件?

问题描述 投票:0回答:1

我的目的是实现将元素从一个列表拖动到另一个列表,例如:

  1. 将layout2元素(有2个嵌套块)拖到编辑器中。
  2. 将段落拖到两个布局块之一中。

我面临的问题是布局块本身不保存任何元素。 将布局块拖到编辑器中时一切正常,但如果将段落拖到布局块中,正如我预期的那样,它会出现,但不会出现。

请检查源代码链接: https://stackblitz.com/edit/stackblitz-starters-dwd2dm?file=src%2FApp.tsx

reactjs react-hooks drag-and-drop draggable react-sortablejs
1个回答
0
投票

此行为的一个可能原因可能与将元素放入布局块时更新状态的方式有关。在 Layout6 组件中,当您将元素放入布局块后更新状态时,您会将新列表与现有内容连接起来:

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

不要直接连接列表([...item.content, ...newList]),而是尝试将内容直接设置到新列表:

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

通过这样做,布局块的内容将被删除的元素替换,而不是附加到现有内容。

我尝试用我的代码替换 L98 - L104,我觉得它有效,因为它不会重复/误解拖动到布局中的组件。

已附

将Layout2和Layout6替换为以下代码,检查是否有效。我尝试用此代码替换它们,现在拖动到 Layout2 和 Layout6 工作正常。

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>
  );
};
© www.soinside.com 2019 - 2024. All rights reserved.