[英]React contentEditable and cursor position
我有简单的组件
class ContentEditable extends React.Component {
constructor(props) {
super(props);
this.handleInput = this.handleInput.bind(this);
}
handleInput(event) {
let html = event.target.innerHTML;
if (this.props.onChange && html !== this.lastHtml) {
this.props.onChange({ target: { value: html, name: this.props.name } });
this.lastHtml = html;
}
}
render() {
return (
<span
contentEditable="true"
onInput={this.handleInput}
className={"auto " + this.props.className}
dangerouslySetInnerHTML={{ __html: this.props.value }}
/>
);
}
}
export default ContentEditable;
<ContentEditable
value={this.state.name}
onChange={e => {
this.setState({ name: e.target.value });
}}
/>;
useRef
的解决方案如下所示。
这里useRef
会在组件渲染周期之外保留默认值/初始值,因此它会保留原始值而不受我们在 react 组件中所做的其他类型的操作的影响。
这个组件做了两件事
onChange
方法将用户输入发送到父组件prop
命名value
并在自定义输入框中呈现值(使用contentEditable
创建)我添加了一个代码沙箱,链接在这里,用它来看看它是如何工作的!
代码沙箱示例包含两个组件
- 一个是
ContentEditableWithRef
,它解决了useRef
的问题,它是一个不受控制的组件,并且- 另一个组件是
ContentEditable
,它使用useState
来解决同样的问题。
我也有同样的问题。 刚刚用ref
修复它。 只需将 event.target 的textContent
分配给ref
。
const textareaEl = useRef<HTMLDivElement>(null);
const handleChange = (e: React.ChangeEvent<HTMLDivElement>) => {
textareaEl.current.textContent = e.target.textContent;
onChange(e); // If you have change event for form/state
};
/** If you're passing value from state,
you can mutate it each change for not losing cursor position.
*/
useEffect(() => {
if (value) {
textareaEl.current.textContent = value;
}
}, [value]);
return (
<div
id="textarea-element"
ref={textareaEl}
contentEditable={true}
suppressContentEditableWarning={true}
onChange={handleChange}
/>
)
import React, { useRef } from 'react';
const ContentEditable = ({ value, onChange = () => {}, ...props }) => {
const state = useRef({ value, prevValue: null, key: null });
if (state.current.prevValue !== value) {
state.current.value = value;
state.current.key = Date.now();
}
const _handleInput = (event) => {
const value = event.target.innerText;
state.current.prevValue = value;
onChange(value);
};
return (
<div
{...props}
key={state.current.key}
role="textbox"
contentEditable={true}
dangerouslySetInnerHTML={{ __html: state.current.value }}
onInput={_handleInput}
/>
);
};
export default ContentEditable;
用法:
const [value, setValue] = useState("initial test");
<ContentEditable
value={value}
onChange={setValue}
/>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.