React-drid-layout – 单击事件

huangapple go评论57阅读模式
英文:

React-drid-layout - onClick event

问题

我需要在<GridLayout>组件上使用onClick处理程序,这是来自react-grid-layout的。思路是,我有一个父<GridLayout>,但我也可以在其中创建新的子布局。但是当我点击父<GridLayout>(而不是它的子项)时,我应该将活动布局设置为1。

我尝试了这段代码:

import "./styles.css";
import GridLayout from "react-grid-layout";
import { useState, useRef } from "react";
import "react-grid-layout/css/styles.css";
import "react-resizable/css/styles.css";

export default function CustomLayout({ layout, onDragStart, onDragStop }) {
  const [isDraggable, setIsDraggable] = useState(true);
  const [active, setActive] = useState(2);
  const gridLayoutRef = useRef(null);

  console.log("state", active);

  const handleClick = (event) => {
    const x = event.nativeEvent.offsetX;
    const y = event.nativeEvent.offsetY;
    const layout = gridLayoutRef.current.state.layout;

    for (let i = 0; i < layout.length; i++) {
      const item = layout[i];
      if (
        x >= item.x &&
        x <= item.x + item.w &&
        y >= item.y &&
        y <= item.y + item.h
      ) {
        setActive(2);
        return;
      }
    }

    setActive(1);
  };

  return (
    <GridLayout
      className="layout"
      onDragStart={onDragStart}
      onDragStop={onDragStop}
      layout={layout}
      cols={12}
      rowHeight={80}
      width={1200}
      isDraggable={isDraggable}
      ref={gridLayoutRef}
    >
      {layout.map((item) => {
        if (item.children) {
          return (
            <div
              key={item.i}
              style={{ background: "pink", border: "1px solid black" }}
            >
              <CustomLayout
                layout={item.children}
                onDragStart={() => {
                  setIsDraggable(false);
                }}
                onDragStop={() => {
                  setIsDraggable(true);
                }}
              />
            </div>
          );
        } else {
          return (
            <div key={item.i} style={{ background: "purple", color: "#fff" }}>
              {item.i}
            </div>
          );
        }
      })}
    </GridLayout>
  );
}

思路很简单 - 我获取了点击的坐标并检查是否存在子元素。但问题在于,onClick事件不起作用。是否有解决此问题的方法?我知道可以创建一个按钮来将状态设置为我想要的状态,但我需要类似于clickOut事件的东西。

如果有人想更仔细地查看,我会留下我的CodeSandbox示例链接:https://codesandbox.io/s/amazing-chatterjee-wzsq62?file=/src/gridLayout.js:0-1882

英文:

I need to somehow use onClick handler on <GridLayout> from react-grid-layout. The idea - I have a parent <GridLayout>, but I can also create new child layouts inside of it. But when I click on parent <Gridlayout> (but not on it's item) i should set active layout to 1.

I tried this code:

import &quot;./styles.css&quot;;
import GridLayout from &quot;react-grid-layout&quot;;
import { useState, useRef } from &quot;react&quot;;
import &quot;react-grid-layout/css/styles.css&quot;;
import &quot;react-resizable/css/styles.css&quot;;
export default function CustomLayout({ layout, onDragStart, onDragStop }) {
const [isDraggable, setIsDraggable] = useState(true);
const [active, setActive] = useState(2);
const gridLayoutRef = useRef(null);
console.log(&quot;state&quot;, active);
const handleClick = (event) =&gt; {
const x = event.nativeEvent.offsetX;
const y = event.nativeEvent.offsetY;
const layout = gridLayoutRef.current.state.layout;
for (let i = 0; i &lt; layout.length; i++) {
const item = layout[i];
if (
x &gt;= item.x &amp;&amp;
x &lt;= item.x + item.w &amp;&amp;
y &gt;= item.y &amp;&amp;
y &lt;= item.y + item.h
) {
setActive(2);
return;
}
}
setActive(1);
};
return (
&lt;GridLayout
className=&quot;layout&quot;
onDragStart={onDragStart}
onDragStop={onDragStop}
layout={layout}
cols={12}
rowHeight={80}
width={1200}
isDraggable={isDraggable}
ref={gridLayoutRef}
&gt;
{layout.map((item) =&gt; {
if (item.children) {
return (
&lt;div
key={item.i}
style={{ background: &quot;pink&quot;, border: &quot;1px solid black&quot; }}
&gt;
&lt;CustomLayout
layout={item.children}
onDragStart={() =&gt; {
setIsDraggable(false);
}}
onDragStop={() =&gt; {
setIsDraggable(true);
}}
/&gt;
&lt;/div&gt;
);
} else {
return (
&lt;div key={item.i} style={{ background: &quot;purple&quot;, color: &quot;#fff&quot; }}&gt;
{item.i}
&lt;/div&gt;
);
}
})}
&lt;/GridLayout&gt;
);
}

The idea is simple - i get the coordinates of my click and check if there is a child element. But here comes the issue - onClick event doesn't work. is there any way to solve this issue? I know can create a button to set my state to what i want it to be, but I need something like a clickOut event. <br/>
I'll leave a link to my CodeSandbox example in case someone wants to have a closer look: https://codesandbox.io/s/amazing-chatterjee-wzsq62?file=/src/gridLayout.js:0-1882

答案1

得分: 2

根据我从你发布的代码中理解的情况,似乎在父级 GridLayout 上未触发 onClick 事件,看起来它不是一个可点击的元素。

如果你将 GridLayout 包裹在一个可点击的容器元素中,比如一个 div,并将 onClick 事件附加到该容器,类似下面这样:

import "./styles.css";
import GridLayout from "react-grid-layout";
import { useState, useRef } from "react";
import "react-grid-layout/css/styles.css";
import "react-resizable/css/styles.css";

export default function CustomLayout({ layout, onDragStart, onDragStop }) {
  const [isDraggable, setIsDraggable] = useState(true);
  const [active, setActive] = useState(2);
  const gridLayoutRef = useRef(null);

  useEffect(() => {
    console.log("state", active);
  }, [active])

  const handleClick = (event) => {
    const x = event.nativeEvent.offsetX;
    const y = event.nativeEvent.offsetY;
    const layout = gridLayoutRef.current.state.layout;

    for (let i = 0; i < layout.length; i++) {
      const item = layout[i];
      if (
        x >= item.x &&
        x <= item.x + item.w &&
        y >= item.y &&
        y <= item.y + item.h
      ) {
        setActive(2);
        return;
      }
    }

    setActive(1);
  };

  return (
    <div onClick={handleClick}>
      <GridLayout
        className="layout"
        onDragStart={onDragStart}
        onDragStop={onDragStop}
        layout={layout}
        cols={12}
        rowHeight={80}
        width={1200}
        isDraggable={isDraggable}
        ref={gridLayoutRef}
      >
        {layout.map((item) => {
          if (item.children) {
            return (
              <div
                key={item.i}
                style={{ background: "pink", border: "1px solid black" }}
              >
                <CustomLayout
                  layout={item.children}
                  onDragStart={() => {
                    setIsDraggable(false);
                  }}
                  onDragStop={() => {
                    setIsDraggable(true);
                  }}
                />
              </div>
            );
          } else {
            return (
              <div key={item.i} style={{ background: "purple", color: "#fff" }}>
                {item.i}
              </div>
            );
          }
        })}
      </GridLayout>
    </div>
  );
}

希望这能有所帮助。如果需要进一步的帮助,请随时告诉我。

英文:

Based on my understanding from the code you posted, onClick event is not being triggered on the parent GridLayout and it looks like it's not a clickable element.

What if you wrap the GridLayout with a clickable container element, such as a div, and attach the onClick event to that container, something like below:

import &quot;./styles.css&quot;;
import GridLayout from &quot;react-grid-layout&quot;;
import { useState, useRef } from &quot;react&quot;;
import &quot;react-grid-layout/css/styles.css&quot;;
import &quot;react-resizable/css/styles.css&quot;;
export default function CustomLayout({ layout, onDragStart, onDragStop }) {
const [isDraggable, setIsDraggable] = useState(true);
const [active, setActive] = useState(2);
const gridLayoutRef = useRef(null);
useEffect(()=&gt;{
console.log(&quot;state&quot;, active);
},[active])
const handleClick = (event) =&gt; {
const x = event.nativeEvent.offsetX;
const y = event.nativeEvent.offsetY;
const layout = gridLayoutRef.current.state.layout;
for (let i = 0; i &lt; layout.length; i++) {
const item = layout[i];
if (
x &gt;= item.x &amp;&amp;
x &lt;= item.x + item.w &amp;&amp;
y &gt;= item.y &amp;&amp;
y &lt;= item.y + item.h
) {
setActive(2);
return;
}
}
setActive(1);
};
return (
&lt;div onClick={handleClick}&gt;
&lt;GridLayout
className=&quot;layout&quot;
onDragStart={onDragStart}
onDragStop={onDragStop}
layout={layout}
cols={12}
rowHeight={80}
width={1200}
isDraggable={isDraggable}
ref={gridLayoutRef}
&gt;
{layout.map((item) =&gt; {
if (item.children) {
return (
&lt;div
key={item.i}
style={{ background: &quot;pink&quot;, border: &quot;1px solid black&quot; }}
&gt;
&lt;CustomLayout
layout={item.children}
onDragStart={() =&gt; {
setIsDraggable(false);
}}
onDragStop={() =&gt; {
setIsDraggable(true);
}}
/&gt;
&lt;/div&gt;
);
} else {
return (
&lt;div key={item.i} style={{ background: &quot;purple&quot;, color: &quot;#fff&quot; }}&gt;
{item.i}
&lt;/div&gt;
);
}
})}
&lt;/GridLayout&gt;
&lt;/div&gt;
);
}

huangapple
  • 本文由 发表于 2023年7月27日 18:59:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76779068.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定