mirror of
https://github.com/m1ngsama/chat-bubbles-for-yt.git
synced 2025-12-24 10:51:21 +00:00
fix(bubble-input): maintain focus by handling blur events
Use forwardRef to expose the content editable element and let the parent component control the focus fix #1 #2
This commit is contained in:
parent
5fba2eceaa
commit
5b86470066
3 changed files with 28 additions and 19 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
import { useState, useCallback, useEffect } from 'react'
|
import { useState, useCallback } from 'react'
|
||||||
import './App.css'
|
import './App.css'
|
||||||
import Chat from './chat'
|
import Chat from './chat'
|
||||||
import Bubble from './bubble'
|
import Bubble from './bubble'
|
||||||
|
|
@ -17,13 +17,6 @@ function App() {
|
||||||
}
|
}
|
||||||
}, [newMessage, messages])
|
}, [newMessage, messages])
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const el = document.querySelector('.bubble.input > div')
|
|
||||||
if (el) {
|
|
||||||
el.focus()
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="App">
|
<div className="App">
|
||||||
<Chat>
|
<Chat>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import React, { useCallback, useState } from 'react'
|
import React, { useCallback, useState, useRef, useEffect } from 'react'
|
||||||
import './bubble-input.css'
|
import './bubble-input.css'
|
||||||
import ContentEditable from './content-editable'
|
import ContentEditable from './content-editable'
|
||||||
|
|
||||||
const BubbleInput = ({ onChange, onSubmit, value }) => {
|
const BubbleInput = ({ onChange, onSubmit, value }) => {
|
||||||
|
const refEditable = useRef()
|
||||||
const [submitted, setSubmitted] = useState(false)
|
const [submitted, setSubmitted] = useState(false)
|
||||||
|
|
||||||
const handleChange = useCallback(
|
const handleChange = useCallback(
|
||||||
|
|
@ -25,7 +26,15 @@ const BubbleInput = ({ onChange, onSubmit, value }) => {
|
||||||
},
|
},
|
||||||
[onSubmit]
|
[onSubmit]
|
||||||
)
|
)
|
||||||
console.log('value:', value)
|
const handleBlur = useCallback(() => {
|
||||||
|
const { current: elDiv } = refEditable
|
||||||
|
if (elDiv) {
|
||||||
|
elDiv.focus()
|
||||||
|
}
|
||||||
|
}, [refEditable])
|
||||||
|
|
||||||
|
useEffect(() => handleBlur(), [handleBlur])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`bubble input ${value.length === 0 ? 'empty' : ''} ${
|
className={`bubble input ${value.length === 0 ? 'empty' : ''} ${
|
||||||
|
|
@ -33,8 +42,10 @@ const BubbleInput = ({ onChange, onSubmit, value }) => {
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<ContentEditable
|
<ContentEditable
|
||||||
|
ref={refEditable}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
|
onBlur={handleBlur}
|
||||||
value={value}
|
value={value}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,14 @@
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
|
|
||||||
class ContentEditable extends React.Component {
|
class ContentEditable extends React.Component {
|
||||||
constructor(props) {
|
|
||||||
super(props)
|
|
||||||
this.refElement = React.createRef()
|
|
||||||
}
|
|
||||||
render() {
|
render() {
|
||||||
|
const { innerRef } = this.props
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={Math.random()}
|
key={Math.random()}
|
||||||
ref={this.refElement}
|
ref={innerRef}
|
||||||
onInput={this.emitChange}
|
onInput={this.emitChange}
|
||||||
onBlur={this.emitChange}
|
onBlur={this.handleBlur}
|
||||||
onKeyDown={this.emitKeyDown}
|
onKeyDown={this.emitKeyDown}
|
||||||
contentEditable
|
contentEditable
|
||||||
spellCheck="false"
|
spellCheck="false"
|
||||||
|
|
@ -21,12 +18,12 @@ class ContentEditable extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps) {
|
shouldComponentUpdate(nextProps) {
|
||||||
const { current: div } = this.refElement
|
const { current: div } = this.props.innerRef
|
||||||
return nextProps.value !== div.innerText
|
return nextProps.value !== div.innerText
|
||||||
}
|
}
|
||||||
|
|
||||||
emitChange = () => {
|
emitChange = () => {
|
||||||
const { current: div } = this.refElement
|
const { current: div } = this.props.innerRef
|
||||||
var value = div.innerText
|
var value = div.innerText
|
||||||
if (this.props.onChange && value !== this.lastValue) {
|
if (this.props.onChange && value !== this.lastValue) {
|
||||||
this.props.onChange({
|
this.props.onChange({
|
||||||
|
|
@ -42,6 +39,14 @@ class ContentEditable extends React.Component {
|
||||||
const { onKeyDown } = this.props
|
const { onKeyDown } = this.props
|
||||||
onKeyDown && onKeyDown(e)
|
onKeyDown && onKeyDown(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleBlur = e => {
|
||||||
|
this.emitKeyDown(e)
|
||||||
|
const { onBlur } = this.props
|
||||||
|
onBlur && onBlur(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ContentEditable
|
export default React.forwardRef((props, ref) => {
|
||||||
|
return <ContentEditable innerRef={ref} {...props} />
|
||||||
|
})
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue