So I'm trying to replace a span with an input when clicked and then replace back when enter key is pressed or when the user clicked outside of it. Here's my code:
const input = useRef<HTMLInputElement>(null);
const span = useRef<HTMLSpanElement>(null);
const [ titleVisible, setTitleVisible ] = useState(true);
const [ title, setTitle ] = useState('title');
const close = (value: string) => {
setTitle(value.trim());
setTitleVisible(true);
}
onclick = e => {
if (!titleVisible && e.composedPath()[0] !== input.current) {
setTitleVisible(true);
}
}
useEffect(() => {
if (span.current) {
span.current.onclick = () => {
setTitleVisible(false);
}
} else {
input.current!.value = title;
input.current!.onkeyup = e => {
if (e.key === 'Enter') close(input.current!.value);
}
}
}, [titleVisible]);
return (
<div className="topInfo">
{ titleVisible ? <span ref={span}>{title}</span> : <input type="text" ref={input} /> }
</div>
);
Thanks in advance!
CodePudding user response:
This is a way to achieve what you want
const [isEditing, setIsEditing] = useState(false);
const [text, setText] = useState('Click to edit');
const inputRef = useRef(null);
function handleClick() {
setIsEditing(true);
}
function handleBlur(event) {
setIsEditing(false);
setText(event.target.value);
}
function handleKeyDown(event) {
if (event.key === 'Enter') {
setIsEditing(false);
setText(event.target.value);
}
}
useEffect(() => {
if (isEditing) {
inputRef.current.focus();
}
}, [isEditing]);
return (
<div>
{isEditing ? (
<input
ref={inputRef}
type="text"
defaultValue={text}
onBlur={handleBlur}
onKeyDown={handleKeyDown}
/>
) : (
<span onClick={handleClick}>{text}</span>
)}
</div>
);