Migrating editable to functional component

This commit is contained in:
Jesús Espino 2021-04-09 21:30:30 +02:00
parent 21a5478b32
commit 57a6ac3bac
4 changed files with 72 additions and 74 deletions

View file

@ -30,7 +30,7 @@ type Props = {
const CardDetail = (props: Props): JSX.Element|null => {
const {cardTree} = props
const [title, setTitle] = useState(cardTree.card.title)
const titleRef = useRef<Editable>(null)
const titleRef = useRef<{focus(selectAll?: boolean): void}>(null)
const titleValueRef = useRef(title)
titleValueRef.current = title

View file

@ -32,7 +32,7 @@ const TableRow = React.memo((props: Props) => {
const {boardTree, onSaveWithEnter} = props
const {board, activeView} = boardTree
const titleRef = useRef<Editable>(null)
const titleRef = useRef<{focus(selectAll?: boolean): void}>(null)
const [title, setTitle] = useState(props.card.title)
const {card} = props
const isManualSort = activeView.sortOptions.length < 1

View file

@ -17,7 +17,7 @@ type Props = {
const ViewHeaderSearch = (props: Props) => {
const {boardTree, intl} = props
const searchFieldRef = useRef<Editable>(null)
const searchFieldRef = useRef<{focus(selectAll?: boolean): void}>(null)
const [isSearching, setIsSearching] = useState(Boolean(props.boardTree.getSearchText()))
const [searchValue, setSearchValue] = useState(boardTree.getSearchText())

View file

@ -1,6 +1,6 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import React, {useRef, useImperativeHandle, forwardRef} from 'react'
import './editable.scss'
@ -17,83 +17,81 @@ type Props = {
onSave?: (saveType: 'onEnter'|'onEsc'|'onBlur') => void
}
export default class Editable extends React.Component<Props> {
private elementRef = React.createRef<HTMLInputElement>()
private saveOnBlur = true
const Editable = (props: Props, ref: React.Ref<{focus: (selectAll?: boolean) => void}>): JSX.Element => {
const elementRef = useRef<HTMLInputElement>(null)
const saveOnBlur = useRef<boolean>(true)
shouldComponentUpdate(): boolean {
return true
const save = (saveType: 'onEnter'|'onEsc'|'onBlur'): void => {
if (props.validator && !props.validator(props.value || '')) {
return
}
if (!props.onSave) {
return
}
if (saveType === 'onBlur' && !saveOnBlur.current) {
return
}
if (saveType === 'onEsc' && !props.saveOnEsc) {
return
}
props.onSave(saveType)
}
save = (saveType: 'onEnter'|'onEsc'|'onBlur'): void => {
if (this.props.validator && !this.props.validator(this.props.value || '')) {
return
}
if (!this.props.onSave) {
return
}
if (saveType === 'onBlur' && !this.saveOnBlur) {
return
}
if (saveType === 'onEsc' && !this.props.saveOnEsc) {
return
}
this.props.onSave(saveType)
}
public focus(selectAll = false): void {
if (this.elementRef.current) {
const valueLength = this.elementRef.current.value.length
this.elementRef.current.focus()
if (selectAll) {
this.elementRef.current.setSelectionRange(0, valueLength)
} else {
this.elementRef.current.setSelectionRange(valueLength, valueLength)
useImperativeHandle(ref, () => ({
focus: (selectAll = false): void => {
if (elementRef.current) {
const valueLength = elementRef.current.value.length
elementRef.current.focus()
if (selectAll) {
elementRef.current.setSelectionRange(0, valueLength)
} else {
elementRef.current.setSelectionRange(valueLength, valueLength)
}
}
}
},
}))
const blur = (): void => {
saveOnBlur.current = false
elementRef.current?.blur()
saveOnBlur.current = true
}
public blur = (): void => {
this.saveOnBlur = false
this.elementRef.current?.blur()
this.saveOnBlur = true
const {value, onChange, className, placeholderText} = props
let error = false
if (props.validator) {
error = !props.validator(value || '')
}
public render(): JSX.Element {
const {value, onChange, className, placeholderText} = this.props
let error = false
if (this.props.validator) {
error = !this.props.validator(value || '')
}
return (
<input
ref={this.elementRef}
className={'Editable ' + (error ? 'error ' : '') + className}
placeholder={placeholderText}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
onChange(e.target.value)
}}
value={value}
title={value}
onBlur={() => this.save('onBlur')}
onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>): void => {
if (e.keyCode === 27 && !(e.metaKey || e.ctrlKey) && !e.shiftKey && !e.altKey) { // ESC
e.stopPropagation()
if (this.props.saveOnEsc) {
this.save('onEsc')
} else {
this.props.onCancel?.()
}
this.blur()
} else if (e.keyCode === 13 && !(e.metaKey || e.ctrlKey) && !e.shiftKey && !e.altKey) { // Return
e.stopPropagation()
this.save('onEnter')
this.blur()
return (
<input
ref={elementRef}
className={'Editable ' + (error ? 'error ' : '') + className}
placeholder={placeholderText}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
onChange(e.target.value)
}}
value={value}
title={value}
onBlur={() => save('onBlur')}
onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>): void => {
if (e.keyCode === 27 && !(e.metaKey || e.ctrlKey) && !e.shiftKey && !e.altKey) { // ESC
e.stopPropagation()
if (props.saveOnEsc) {
save('onEsc')
} else {
props.onCancel?.()
}
}}
readOnly={this.props.readonly}
/>
)
}
blur()
} else if (e.keyCode === 13 && !(e.metaKey || e.ctrlKey) && !e.shiftKey && !e.altKey) { // Return
e.stopPropagation()
save('onEnter')
blur()
}
}}
readOnly={props.readonly}
/>
)
}
export default forwardRef(Editable)