我有一个在DOM中手动编辑的文本节点,当调用render()
方法时,该节点不会被React更新。
使用官方React网站中的示例演示
class TodoApp extends React.Component {
constructor(props) {
super(props);
this.state = { items: [], text: '' };
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
render() {
return (
<div>
<h3>TODO</h3>
<TodoList items={this.state.items} />
<form onSubmit={this.handleSubmit}>
<label htmlFor="new-todo">
What needs to be done?
</label>
<input
id="new-todo"
onChange={this.handleChange}
value={this.state.text}
/>
<button>
Add #{this.state.items.length + 1}
</button>
</form>
</div>
);
}
handleChange(e) {
this.setState({ text: e.target.value });
}
handleSubmit(e) {
e.preventDefault();
if (this.state.text.length === 0) {
return;
}
const newItem = {
text: this.state.text,
id: Date.now()
};
this.setState(state => ({
items: state.items.concat(newItem),
text: ''
}));
}
}
class TodoList extends React.Component {
render() {
return (
<ul>
{/* Note: using contentEditable only for the purpose of this demo */}
{this.props.items.map(item => (
<li key={item.id} contentEditable={true}>{item.text}</li>
))}
</ul>
);
}
}
ReactDOM.render(
<TodoApp />,
document.getElementById('todos-example')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="todos-example"></div>
我只为这个演示添加了contentEditable
(我没有试图更新todo项),当您添加一个新项,然后在DOM中直接编辑它,然后添加另一个项,为什么之前编辑的项没有被更新到它以前的状态?
编辑:
为什么要这样做?我有一个应用程序,用户可以点击编辑按钮并开始直接编辑文本,我添加contentEditable
属性并使用onInput
存储已编辑的文本,并使用传递的函数更新父级的状态,我想解决的是当用户取消编辑时,我想恢复以前的文本,我目前正在做的是直接编辑该元素的innerText
,以设置以前的值,因为它没有被React更新。
发布于 2020-03-30 04:04:03
您有这个问题,因为React有一个虚拟DOM,它可以比较更改。当您修改真正的DOM时,React不知道您修改了它,所以当它将其虚拟DOM与新的render()
进行比较时,不会看到该元素的任何更改,因此不会重新呈现。
如果您控制了所有反应组件中的HTML,不要直接修改DOM,永远不要。您应该在用户操作上添加事件侦听器(在本例中为keypress),以捕获它们并相应地更新组件状态。如果这样做,您必须了解反应虚拟DOM作品是如何实现的。
发布于 2020-03-30 04:04:35
如果state
或props
保持不变,组件将不会重新呈现。因此,如果要重新呈现组件,则手动编辑必须更新某些状态。
所以,我相信你可以做同样的事情,但“反应方式”,而不是手动。其他人,使用反应有什么意义?
编辑
如果内容可编辑为“必须有”(您不能在div和文本区域之间切换),如果我是您-将添加:
tempEdit
to state或selected
--如果需要将对象保存在状态的该部分中。如果选择对象,也可以在这里保留原始文本--如果用户选择取消编辑,则可以使用后者。onBlur
,请使用它恢复已编辑元素中的文本发布于 2020-03-31 03:21:50
我使用key
属性解决了这个问题,强制响应重新创建DOM元素,我不知道这是否是最好的方法,但这是我发现的最干净的方法,当用户在更改文本后取消编辑时,让我恢复contentEditable
元素的文本。
我有一个edit
状态属性,我切换该属性使元素可编辑,因此我添加了一个key
,其中包含该属性的字符串值:
<p
contentEditable={this.state.edit}
suppressContentEditableWarning="true"
onInput={this.handleInput}
onKeyDown={this.handleKeyDown}
key={String(this.state.edit)}
>
{item.text}
</p>
这有一个缺点,React将在edit
状态的每一次更改上重新创建元素。
最终,contentEditable
并不是所有情况下的最佳解决方案,但是当您需要在不添加新元素的情况下提供编辑解决方案时,这可以完成任务。
https://stackoverflow.com/questions/60929947
复制