反应:仅在单击 html 元素时执行一次操作
React: Perform action, only once, when html element is clicked
在jQuery中,当html
元素上触发事件时,只执行一次操作是非常简单的。
例如:
$(".dropdown-trigger").on("click", function(event) {
var self = this;
$("html").one("click", function() {
$(self).parents(".dropdown").removeClass("active");
});
$(this).parents(".dropdown").toggleClass("active");
event.stopPropagation();
});
在 React 中,这并不容易。
如何在 React 中执行一个操作,当 html 元素被点击时,并且只执行一次该操作(类似于我的 jQuery 代码)?
使用 useState,也适用于 React> 16.8
import React, { useState } from 'react';
const App = () => {
const [clicked, setClicked] = useState(false);
const myFunc = () => alert('hey');
const onClick = (event) => {
if (!clicked) {
setClicked(true);
myFunc(event);
}
};
return <button onClick={onClick}>Click on me (once)</button>;
};
使用 refs。不是很美,但至少它有效。这需要 React>16.8
import React, { useEffect, useRef } from 'react'
const App = () => {
const ref = useRef()
// Wait for DOM to load
useEffect(() => ref.addEventListener('click', () => alert('Hi'), { once: true })
return <button ref={ref}>Click on me (once)</button>
}
翻转状态 元素触发其事件后,react 将重新渲染组件,因为您的状态发生了变化并且不会显示它。以下是实现该结果的一种方法示例。
_onEvent() {
this.setState({
hasTriggered: true
})
}
render() {
return (
<div>
{
!this.state.hasTriggered ?
<MyElement onClick={this._onEvent.bind(this)} /> : null
}
</div>
)
}
函数式编程的高阶方法
裁判:
https://betterprogramming.pub/how-to-allow-only-one-click-events-in-javascript-72938027fbf5
要点:
const once = (f) => {
let finished = false;
return (...args) => {
if (!finished) {
finished = true;
f(...args);
}
};
};
完整示例:
- 答题器 0 将在每次点击时触发事件。
- 这是有问题的。
- 如果网络速度很慢并且用户再次单击希望数据提交得更快,这可能会导致服务器端的额外触发器。
- Clicker 1 只会在按钮本身和点击函数 ref 重新渲染后再次触发。
- 如果我们必须在服务器响应后重新渲染主组件,这是一个简单的解决方案。
- 只有当 value2 有任何更改时,Locker 2 才会再次触发。
- 如果我们想使用特定状态进行控制
import "./App.css";
import { useState, useCallback } from "react";
const once = (f) => {
let finished = false;
return (...args) => {
if (!finished) {
finished = true;
f(...args);
}
};
};
function App() {
const [value1, setValue1] = useState("value1");
const [value2, setValue2] = useState("value2");
console.log(`app rendered`);
const onChange1 = useCallback((e) => {
console.log(`onChange1`, e.target.value);
setValue1(e.target.value);
}, []);
const onChange2 = useCallback((e) => {
console.log(`onChange2`, e.target.value);
setValue2(e.target.value);
}, []);
const onClick0 = () => {
// mocking 2 secs network request
setTimeout(() => {
// set value to value1 to cause the re-render
setValue1(new Date());
console.log("clicker 0");
}, 2000);
};
const onClick1 = () => {
// mocking 2 secs network request
setTimeout(() => {
// set value to value1 to cause the re-render
setValue1(new Date());
console.log("clicker 1");
}, 2000);
};
const onClick2 = () => {
// mocking 2 secs network request
setTimeout(() => {
// set value to value1 to cause the re-render
setValue1(new Date());
console.log("clicker 2");
}, 2000);
};
const memoOnceOnClick2 = useCallback(once(onClick2), [value2]);
return (
<div className="App">
<header className="App-header">
<input value={value1} onChange={onChange1} />
<input value={value2} onChange={onChange2} />
<button onClick={onClick0}>
clicker 0 / run every time i am clicked
</button>
<button onClick={once(onClick1)}>
clicker 1 / run once until i am re-render
</button>
<button onClick={memoOnceOnClick2}>
clicker 2 / run once until value2 is changed
</button>
</header>
</div>
);
}
export default App;
在我看来,这是一个更简单的解决方案:
<div
className={`tile ${tile.marked ? "team1" : ""}`}
onClick={!tile.marked ? () => markTile(tile.id) : null}
></div>
这是 React 18 的。如您所见,我正在通过检查标记的属性是否为 false 来检查我是否已经单击了它。只有这样,我才能调用我的函数。
相关文章:
- Javascript返回值只在循环中返回一次
- Jquery FadeIn FadeOut 只工作一次
- Rails操作只调用一次,但我在ajax中每秒钟都调用一次
- Chrome扩展程序:浏览器操作单击按钮工作一次
- jQuery如果大于则执行操作,但只执行一次
- nodejs:原子文件替换操作,只触发一次一些观察者
- 使用getElementById一次指定两个操作
- 如何在一次点击(而不是整个点击)内执行一次操作
- 当您滚动到特定页面位置时,如何执行此操作,该功能将启动一次
- 反应:仅在单击 html 元素时执行一次操作
- 重置选择的一次表单的操作侦听器
- 对多个滚动事件执行一次操作并防止滚动
- JQuery 单击操作只工作一次
- 循环遍历数组,然后在最后一次出现后执行某些操作
- 如果之前在X秒内调用,则阻止并排队执行操作(但仅全局执行一次)
- 每10秒操作一次DOM元素
- Three.js/WebGL一次加载大量纹理数据,操作方法
- 为什么对每个订阅者调用一次(重复)可观察操作?
- jquery每60秒执行一次不同的操作
- Jquery:检查窗口是否滚动过一次并执行一些操作