【发布时间】:2020-10-29 18:54:52
【问题描述】:
tl;博士:
React-grid-layout 在启用和禁用(切换)静态选项时错误地移动所有网格项。我希望网格项目在静态时被冻结,并且当且仅当用户移动它们时才移动它们与静态模式禁用。 An example of the problem can be found here (CodeSandbox),带有GIF example here (Imgur)。
背景
我正在使用react-grid-layout 为我的应用程序制作交互式网格布局。我有一个按钮可以在 non-static(可拖动和可调整大小)和 static(非交互)模式之间切换网格中的所有项目 (info about static in react-grid-layout)。我正在使用useState 和来自this answer 的提示这样做:
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 和 non-static 模式之间切换时,所有值都应保持不变,除了每个对象中的 static 键。屏幕上的位置和大小也应该保持不变。这使用户可以关闭 static 模式以更改网格项目的位置/大小,并打开以将它们“冻结”在它们离开它们的位置/大小。
当前(错误)行为:
我的问题是,当我处于 非静态 模式时,我将网格项目拖到我想要的位置,然后打开 static 模式,它们会重置为他们以前在哪里。即:
我将元素 A 拖到堆栈的底部,当我打开静态模式时,它会移动到堆栈的中间,然后再关闭它会将元素 A 返回到堆栈的顶部。然后元素 A 将在中间和顶部之间循环,具体取决于静态模式是打开还是关闭。
这是我的意思的一个例子:
我的尝试:
- 如 sn-p(注释代码)所示,我尝试重新创建
toggleStaticMode函数以提供更多详细信息。我创建了isStatic状态,并在每次点击时设置它的新值。 - 我还尝试更改位置以查看是否可以在单击时看到位置更改,我可以。如果不对尺寸和位置进行任何修改,值将保持不变,但屏幕上的位置和/或尺寸会发生变化。
- 我还尝试更改每个对象的
static值以保持为真或假以记录更改。当对象a和c的static值为真并且b的值为isStatic时,切换静态模式会改变b以及a和c的位置。控制台中打印的值表示它们没有改变。
以上都没有告诉我发生了什么或为什么会发生。文档也没有提供太多关于此的信息。
一个可能有效的“hackish”解决方案是使用本地存储/cookiesfrom this example,但我不想在每次用户切换静态模式时都这样做。此解决方案实际上可能无法解决此问题。
这可能是一个错误,但如果可能的话,我想找到一个更好的解决方法。
使用的完整代码:
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>
我还 uploaded this code to CodeSandbox 展示了我当前问题的完整工作示例。
这个例子不同在于它使用反应类/状态而不是useState,但同样的问题发生了。此示例显示了切换静态模式时大小/位置值的变化。
编辑:
Someone Special 的回答让我朝着正确的方向前进,但是,当列重新排列为小于最小大小的值时,项目再次在切换时分散。 can be viewed here 的一个例子。
【问题讨论】:
标签: javascript reactjs next.js react-grid-layout