https://codesandbox.io/s/react-textarea-callback-on-blur-yoh8n?file=/src/App.tsx
प्रतिक्रिया में एक textarea होने के कारण मैं दो बुनियादी उपयोग के मामलों को प्राप्त करना चाहता हूं:
- जब उपयोगकर्ता "एस्केप" दबाता है तो फ़ोकस निकालें और कुछ स्थिति रीसेट करें
- कॉलबैक निष्पादित करें (
saveToDatabase
) जब उपयोगकर्ता टेक्स्ट क्षेत्र के बाहर क्लिक करता है और यह फोकस खो देता है (=>onBlur
)
<textarea
ref={areaRef}
value={input}
onChange={handleChange}
onKeyDown={handleKeyDown}
onBlur={handleBlur}
/>
पहले उपयोग के मामले में मैं लक्ष्य पर blur()
को कॉल कर रहा हूं:
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (e.key === "Escape") {
console.log("Escape clicked");
setInput(inputForReset);
e.currentTarget.blur();
}
};
..लेकिन यह onBlur
हैंडलर को भी कॉल करता है, जिसे मैं वास्तव में दूसरे उपयोग के मामले के लिए उपयोग करना चाहता हूं। मैंने यह निर्धारित करने का प्रयास किया कि ईवेंट कॉलर टेक्स्टरेरा स्वयं एक रेफरी के माध्यम से है, लेकिन यह काम नहीं करता है:
const handleBlur = (e: React.FocusEvent<HTMLTextAreaElement>) => {
console.log("blur");
/**
* Only save to database when losing focus through clicking
* outside of the text area, not for every blur event.
*/
if (areaRef.current && !areaRef.current.contains(e.currentTarget as Node)) {
saveToDatabase();
}
};
दूसरे शब्दों में: जब उपयोगकर्ता टेक्स्टरेरा में संपादन समाप्त कर लेता है, तो मैं डेटाबेस में कुछ सहेजना चाहता हूं, लेकिन मुझे नहीं पता कि blur
ईवेंट के बीच अंतर कैसे करें, मैंने प्रोग्रामेटिक रूप से ट्रिगर किया और मूल blur
जब आप नोड के बाहर क्लिक करते हैं तो टेक्स्टरेरा उपयोग करता है।
2 जवाब
मैंने देखा कि त्रुटि क्या है। ब्लर इवेंट का टारगेट खुद होता है
areaRef === event.target
तो आपको बॉक्स के बाहर क्लिक पकड़ने के लिए एक अतिरिक्त फ़ंक्शन लागू करना होगा।
import * as React from "react";
import "./styles.css";
import { useState, useRef, useEffect } from "react";
function useOutsideAlerter(
ref: React.RefObject<HTMLTextAreaElement>,
fun: () => void
) {
useEffect(() => {
function handleClickOutside(event: any) {
if (
ref.current &&
!ref.current.contains(event.target) &&
// THIS IS IMPORTANT TO CHECK
document.activeElement === ref.current
) {
fun();
}
}
// Bind the event listener
document.addEventListener("mousedown", handleClickOutside);
return () => {
// Unbind the event listener on clean up
document.removeEventListener("mousedown", handleClickOutside);
};
}, [ref]);
}
export default function App() {
const areaRef = useRef<HTMLTextAreaElement>(null);
const [inputForReset, setInputForReset] = useState<string>("Original input");
const [input, setInput] = useState<string>(inputForReset);
const saveToDatabase = () => {
console.log("save to database");
setInputForReset(input);
alert(input);
};
// OUT SIDE CLICK
useOutsideAlerter(areaRef, saveToDatabase);
const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
setInput(e.target.value);
};
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (e.key === "Escape") {
console.log("Escape clicked");
setInput(inputForReset);
e.currentTarget.blur();
e.stopPropagation();
}
};
// it doesnt work
const handleBlur = (e: React.FocusEvent<HTMLTextAreaElement>) => {
/**
* Only save to database when losing focus through clicking
* outside of the text area, not for every blur event.
*/
console.log(event.target);
console.log(areaRef);
if (areaRef.current && !areaRef.current.contains(event.target)) {
saveToDatabase();
}
};
return (
<div className="App">
<textarea
ref={areaRef}
value={input}
onChange={handleChange}
onKeyDown={handleKeyDown}
onBlur={handleBlur}
className="area"
/>
<p>Input state: {input}</p>
</div>
);
}
कृपया मेरा sandboxदेखें। ए>
हो सकता है कि आप "preventsaveOnBlur" ध्वज के रूप में एक चर (या एक वर्ग संपत्ति, यदि आप एक कार्यात्मक के बजाय वर्ग घटक का उपयोग कर रहे हैं) जोड़ सकते हैं; कुछ इस तरह:
let preventSaveOnBlur: boolean = false;
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (e.key === "Escape") {
console.log("Escape clicked");
setInput(inputForReset);
preventSaveOnBlur = true; // will prevent saving on DB - see handleBlur
e.currentTarget.blur();
}
};
const handleBlur = (e: React.FocusEvent<HTMLTextAreaElement>) => {
console.log("blur");
/**
* Only save to database when losing focus through clicking
* outside of the text area, not for every blur event.
*/
if (!preventSaveOnBlur) {
saveToDatabase();
}
};
const handleFocus = (e: React.FocusEvent<HTMLTextAreaElement>) => {
preventSaveOnBlur = false;
};
और टेक्स्टरेरा में आप ऑनफोकस ईवेंट भी संभालते हैं:
<textarea
ref={areaRef}
value={input}
onChange={handleChange}
onKeyDown={handleKeyDown}
onBlur={handleBlur}
onFocus={handleFocus} // will reset 'preventSaveOnBlur' to false every time the textarea get the focus
/>