React项目中如何将contentEditable内容保存至state数组?
问题分析与解决方案
你现在的核心问题是把拖拽组件的onChange和内容编辑的事件搞混了:Draggable组件的onChange是监听拖拽位置变化的,和contentEditable元素的编辑行为完全无关,所以你编辑文本时根本不会触发这个回调。另外你的Note组件还漏接收了id属性,父组件传了但没解构。
修复步骤:
给可编辑元素绑定正确的输入事件
对contentEditable="true"的<p>标签,应该监听onInput(实时响应输入)或者onBlur(失去焦点时保存)事件,获取当前编辑的内容后传给父组件。正确更新父组件的notes数组
父组件的handleOnChange需要根据id找到对应note,更新它的content,这里要用函数式更新setNotes(prev => ...),确保拿到最新的状态。
修改后的完整代码:
// 修正Note组件:接收id,给可编辑p绑定输入事件 function Note({ id, content, onWrite }) { const handleContentChange = (e) => { // 获取当前编辑的内容,用textContent避免HTML标签,或者innerHTML保留格式 const newContent = e.target.textContent; onWrite(id, newContent); }; return ( <Draggable bounds="parent" axis="both"> <div className="note"> <p contentEditable="true" onInput={handleContentChange}> {content} </p> </div> </Draggable> ); } function App() { const [notes, setNotes] = useState([]); // 修正handleOnChange:根据id更新对应note的内容 function handleOnChange(noteId, newContent) { console.log('A note was changed'); setNotes(prevNotes => prevNotes.map(note => note.id === noteId ? { ...note, content: newContent } : note ) ); } return ( <div className="App"> <h1>THIS IS A TEST</h1> <button onClick={() => { const newNote = { id: uuid(), content: 'Type something' }; setNotes(prev => [...prev, newNote]); // 注意:setState是异步的,直接log notes拿不到最新值,要log newNote或者用useEffect监听变化 console.log(newNote); }}>+</button> <div className="notes"> {notes.map(note => ( <Note key={note.id} id={note.id} {/* 补上id属性传递 */} content={note.content} onWrite={handleOnChange} /> ))} </div> </div> ); }
额外提示:
- 如果不想实时更新,把
onInput换成onBlur,只会在用户离开便签时保存内容,减少状态更新次数 contentEditable会生成HTML标签,如果不需要格式,用textContent获取内容;需要保留格式的话用innerHTML- 原代码中点击按钮后
console.log(notes)拿不到最新值,因为setNotes是异步的,要么log新创建的newNote,要么用useEffect监听notes变化再打印
内容的提问来源于stack exchange,提问作者Metaphysical Madman
相关产品推荐
相关产品推荐

