0

tl;dr:

React-grid-layoutは、静的オプションが有効または無効 (トグル) の場合に、すべてのグリッド アイテムを誤って移動します。静的な場合はグリッド項目を所定の位置に固定し、ユーザーが静的モードを無効にして移動した場合にのみ移動します。問題の例はこちら (CodeSandbox)で、GIF の例はこちら (Imgur)にあります。


バックグラウンド

react-grid-layoutを使用して、アプリのインタラクティブなグリッド レイアウトを作成しています。グリッド内のすべてのアイテムに対して非静的(ドラッグ可能およびサイズ変更可能) モードと静的(非インタラクティブ) モードを切り替えるボタンがあります( react-grid-layout の静的に関する情報)。私はこの答えuseStateからのヒントを使ってそうしています:

var [layout, setLayout] = useState([
  { i: "a", x: 0, y: 0, w: 10, h: 4, static: false },
  { i: "b", x: 1, y: 0, w: 3, h: 2, static: false },
  { i: "c", x: 4, y: 0, w: 1, h: 2, static: false },
]);

function toggleStaticMode() {
  setLayout(
    layout.map((prevLayout) => {
      return { ...prevLayout, static: !prevLayout.static };
    })
  );
}

予想される動作:

グリッド内の各要素には、グリッド レイアウト上での位置、サイズなどを定義する固有のプロパティがあります。これらはlayout上記の変数で定義されています。静的モードと非静的モードを切り替える場合、各オブジェクトのキーを除いて、すべての値は同じままにする必要があります。画面上の位置とサイズも同じままにする必要があります。これにより、ユーザーは静的モードをオフに切り替えてグリッド項目の位置/サイズを変更し、オンにすると、それらを残した場所/サイズで「フリーズ」できます。static

現在の (間違った) 動作:

私の問題は、非静的モードのときです。グリッド項目を必要な場所にドラッグし、静的モードをオンにすると、以前の場所にリセットされます。すなわち:

要素 A をスタックの一番下にドラッグし、静的モードをオンにするとスタックの中央に移動し、オフに戻すと要素 A がスタックの一番上に戻ります。要素 A は、静的モードがオンかオフかに応じて、中央と上部の間でループします。

これが私が意味することの例です:


私が試したこと

  • toggleStaticModeスニペット (コメント付きのコード) に示されているように、詳細を提供するために関数を再作成してみました。状態を作成し、isStaticクリックごとに新しい値を設定しました。
  • また、クリックで位置が変化するかどうかを確認するために、位置を変更しようとしました。サイズと位置を変更しなければ、値は同じままですが、画面上の位置やサイズが変更されます。
  • また、変更staticに注意するために、各オブジェクトの値を true または false のままに変更してみました。オブジェクトacstatic値が true で がbの場合isStatic、静的モードを切り替えるとb、 とaの位置が変更されましたc。コンソールに出力された値は、変更されていないことを示しています。

上記のどれも、何が起こっていたのか、なぜそうなったのかを示していませんでした。ドキュメントもこれに関する多くの情報を提供しませんでした。

機能する可能性のある「ハック」ソリューションの 1 つは、この例のローカル ストレージ/Cookie を使用することですが、ユーザーが静的モードを切り替えるたびにこれを実行したくありません。この解決策は、実際にはこの問題を解決しない可能性があります。

これはバグかもしれませんが、可能であればより良い回避策を見つけたいと思います。


使用される完全なコード:

import React, {
  useState
} from "react";
import GridLayout from "react-grid-layout";

export default function Home() {
  let [layout, setLayout] = useState([{
      i: "a",
      x: 1,
      y: 0,
      w: 8,
      h: 4,
      static: false
    },
    {
      i: "b",
      x: 3,
      y: 2,
      w: 3,
      h: 2,
      static: false
    },
    {
      i: "c",
      x: 5,
      y: 4,
      w: 1,
      h: 2,
      static: false
    },
  ]);

  function printLayoutItem(val) {
    console.log(layout[val].i + ": (w: " + layout[val].w + " h: " + layout[val].h + " x: " + layout[val].x + " y: " + layout[val].y + ")");
  }

  function toggleStaticMode() {
    setLayout(
      layout.map((l) => {
        return { ...l,
          static: !l.static
        };
      })
    );
  }

  // let [isStatic, setStatic] = useState(false);

  // function toggleStaticMode() {
  //    if (isStatic) setStatic(false) 
  //    else setStatic(true);
  //    printLayoutItem(0);
  //    printLayoutItem(1);
  //    printLayoutItem(2);
  //    setLayout([
  //        { i: "a", x: 3, y: 0, w: 8, h: 4, static: isStatic },
  //        { i: "b", x: 0, y: 2, w: 3, h: 2, static:  isStatic},
  //        { i: "c", x: 5, y: 4, w: 1, h: 2, static: isStatic },
  //    ]);
  // }

  return ( <div>
    <main>{/* thanks for this beautiful Tidy, StackOverflow */}
    <button onClick ={toggleStaticMode}>
    Toggle Static Mode
    </button> 
    <GridLayout 
        className="layout"
        layout={layout}
        cols={4}
        rowHeight={100}
        width={1200}>
    <div key="a">Hello A </div> 
    <div key="b">Hello B </div> 
    <div key="c">Hello C </div> 
    </GridLayout > 
   </main> 
   </div>
  );
}
<!-- Snippet does not run correctly, please see the example below for a working example of the error occuring -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

また、このコードを CodeSandbox にアップロードして、現在の問題の完全な動作例を示しました。この例は、react クラス/ステートを使用する方法と を使用しない方法が異なりuseStateますが、同じ問題が発生します。この例は、静的モードを切り替えたときにサイズ/位置の値が変化することを示しています。

編集:

特別な誰かの答えは正しい方向に私を導きましたが、列が最小サイズよりも小さい値に再配置されると、アイテムは再びトグル時に散らばります。この例は、ここで見ることができます

4

1 に答える 1