Reputation: 1242
I'm having an interesting issue that I cannot debug.
Goal
On a class component, inside of render function, iterate over an array of objects from state
using this.state.items.map((item, index) => {})
and return a contentEditable
paragraph element.
On each contentEditable
paragraph element, listen for the onKeyUp
event. If the key being used from e.which
is the enter (13) key, add a new item to this.state.items
using the index of the element that was keyed, in order to insert a new element after that index using splice
.
Seeing Expected Result?
No. The newly added item is instead being put at the end of the loop when it is being rendered.
Example situation and steps to reproduce:
P
elementP
element is created and focused)P
elementP
element, either by shift+tab or clickingP
element is created and focused, but it is at the end of the list and not where it is intended to be, which is between the "test1" and "test2" P
elementsHere is the code that I have so far:
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
Here is a jsfiddle with the code from above.
If you take the above steps, you will see the issue that I am having.
Let me know if you require any further information, thanks in advance!
P.S. Please let me know if there any improvements that I can make to the code. I have been working in React for a short amount of time, and would love any feedback on how to make it better/cleaner.
UPDATED
Added key={index}
to the P
element. Note: this does not reflect any answers, it was merely added to stay in line with ReactJS list rendering.
Upvotes: 0
Views: 4530
Reputation: 416
to render a list of items, React needs key to keep track of the element see this: https://reactjs.org/docs/lists-and-keys.html
here is your updated fiddle that working..
<p ref={item.ref}
key={item.id}
contentEditable
suppressContentEditableWarning
onKeyUp={e => this.handleParagraphKeyUp(e,
Upvotes: 2