ReactJS class 组件渲染 array.map 使用 contenteditable 元素
ReactJS class component render array.map using contenteditable elements
我遇到了一个无法调试的有趣问题。
目标
在 class 组件上,在渲染函数内部,使用 this.state.items.map((item, index) => {})
和 return 迭代 state
中的对象数组 contentEditable
段落元素.
在每个 contentEditable
段落元素上,监听 onKeyUp
事件。如果从 e.which
使用的键是 enter (13) 键,则使用键控元素的索引向 this.state.items
添加一个新项目,以便在该索引之后插入一个新元素使用splice
.
看到预期结果了吗?
没有。新添加的项目在渲染时被放在循环的末尾。
示例情况和重现步骤:
- 在第一个
P
元素中输入 "test1"
- 按回车键(创建并聚焦新的
P
元素)
- 在第二个新创建的
P
元素中键入 "test2"
- 重新关注第一个
P
元素,通过 shift+tab 或点击
- 回车
- 查看观察到的结果:一个新的
P
元素被创建并获得焦点,但它位于列表的末尾而不是预期的位置,它位于 "test1" 和"test2" P
个元素
这是我目前的代码:
class MyComponent extends React.Component {
constructor(props) {
super(props)
this.state = {
items: [this.paragraphTemplate()]
}
}
render() {
return (
<section>
<div>
{this.state.items.map((item, index) => {
return <p ref={item.ref}
key={index}
contentEditable
suppressContentEditableWarning
onKeyUp={e => this.handleParagraphKeyUp(e, index, item)}></p>
})}
</div>
</section>
)
}
handleParagraphKeyUp = (e, index, item) => {
if (e.which === 13) {
let addition = this.paragraphTemplate()
this.setState(state => {
state.items.splice(index + 1, 0, addition)
return {
blocks: state.items
}
}, () => {
addition.ref.current.focus()
/* clear out the br and div elements that the browser might auto-add on "enter" from the element that was focused when the "enter" key was used */
this.state.items[index].ref.current.innerHTML = this.state.items[index].ref.current.innerHTML.replace(/<br\s*[\/]?>/gi, '').replace(/<[\/]?div>/gi, '')
})
return false
}
}
paragraphTemplate = () => {
return {
ref: React.createRef()
}
}
}
export default MyComponent
这是一个 jsfiddle 上面的代码。
如果您执行上述步骤,您将看到我遇到的问题。
如果您需要任何进一步的信息,请告诉我,在此先感谢!
P.S。如果我可以对代码进行任何改进,请告诉我。我已经在 React 中工作了很短的时间,并且希望收到有关如何制作它的任何反馈 better/cleaner。
已更新
向 P
元素添加了 key={index}
。注意:这并不反映任何答案,它只是为了与 ReactJS 列表渲染保持一致而添加的。
要呈现项目列表,React 需要键来跟踪元素
看到这个:https://reactjs.org/docs/lists-and-keys.html
这是您更新后的 fiddle 工作..
<p ref={item.ref}
key={item.id}
contentEditable
suppressContentEditableWarning
onKeyUp={e => this.handleParagraphKeyUp(e,
我遇到了一个无法调试的有趣问题。
目标
在 class 组件上,在渲染函数内部,使用 this.state.items.map((item, index) => {})
和 return 迭代 state
中的对象数组 contentEditable
段落元素.
在每个 contentEditable
段落元素上,监听 onKeyUp
事件。如果从 e.which
使用的键是 enter (13) 键,则使用键控元素的索引向 this.state.items
添加一个新项目,以便在该索引之后插入一个新元素使用splice
.
看到预期结果了吗?
没有。新添加的项目在渲染时被放在循环的末尾。
示例情况和重现步骤:
- 在第一个
P
元素中输入 "test1" - 按回车键(创建并聚焦新的
P
元素) - 在第二个新创建的
P
元素中键入 "test2" - 重新关注第一个
P
元素,通过 shift+tab 或点击 - 回车
- 查看观察到的结果:一个新的
P
元素被创建并获得焦点,但它位于列表的末尾而不是预期的位置,它位于 "test1" 和"test2"P
个元素
这是我目前的代码:
class MyComponent extends React.Component {
constructor(props) {
super(props)
this.state = {
items: [this.paragraphTemplate()]
}
}
render() {
return (
<section>
<div>
{this.state.items.map((item, index) => {
return <p ref={item.ref}
key={index}
contentEditable
suppressContentEditableWarning
onKeyUp={e => this.handleParagraphKeyUp(e, index, item)}></p>
})}
</div>
</section>
)
}
handleParagraphKeyUp = (e, index, item) => {
if (e.which === 13) {
let addition = this.paragraphTemplate()
this.setState(state => {
state.items.splice(index + 1, 0, addition)
return {
blocks: state.items
}
}, () => {
addition.ref.current.focus()
/* clear out the br and div elements that the browser might auto-add on "enter" from the element that was focused when the "enter" key was used */
this.state.items[index].ref.current.innerHTML = this.state.items[index].ref.current.innerHTML.replace(/<br\s*[\/]?>/gi, '').replace(/<[\/]?div>/gi, '')
})
return false
}
}
paragraphTemplate = () => {
return {
ref: React.createRef()
}
}
}
export default MyComponent
这是一个 jsfiddle 上面的代码。
如果您执行上述步骤,您将看到我遇到的问题。
如果您需要任何进一步的信息,请告诉我,在此先感谢!
P.S。如果我可以对代码进行任何改进,请告诉我。我已经在 React 中工作了很短的时间,并且希望收到有关如何制作它的任何反馈 better/cleaner。
已更新
向 P
元素添加了 key={index}
。注意:这并不反映任何答案,它只是为了与 ReactJS 列表渲染保持一致而添加的。
要呈现项目列表,React 需要键来跟踪元素 看到这个:https://reactjs.org/docs/lists-and-keys.html
这是您更新后的 fiddle 工作..
<p ref={item.ref}
key={item.id}
contentEditable
suppressContentEditableWarning
onKeyUp={e => this.handleParagraphKeyUp(e,