From 57a6ac3bac8e0bfacb6d8c12bf8f7c30f240e041 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Fri, 9 Apr 2021 21:30:30 +0200 Subject: [PATCH] Migrating editable to functional component --- .../src/components/cardDetail/cardDetail.tsx | 2 +- webapp/src/components/table/tableRow.tsx | 2 +- .../viewHeader/viewHeaderSearch.tsx | 2 +- webapp/src/widgets/editable.tsx | 140 +++++++++--------- 4 files changed, 72 insertions(+), 74 deletions(-) diff --git a/webapp/src/components/cardDetail/cardDetail.tsx b/webapp/src/components/cardDetail/cardDetail.tsx index d890f10a9..39576087f 100644 --- a/webapp/src/components/cardDetail/cardDetail.tsx +++ b/webapp/src/components/cardDetail/cardDetail.tsx @@ -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(null) + const titleRef = useRef<{focus(selectAll?: boolean): void}>(null) const titleValueRef = useRef(title) titleValueRef.current = title diff --git a/webapp/src/components/table/tableRow.tsx b/webapp/src/components/table/tableRow.tsx index dd4bcd235..22f4e3272 100644 --- a/webapp/src/components/table/tableRow.tsx +++ b/webapp/src/components/table/tableRow.tsx @@ -32,7 +32,7 @@ const TableRow = React.memo((props: Props) => { const {boardTree, onSaveWithEnter} = props const {board, activeView} = boardTree - const titleRef = useRef(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 diff --git a/webapp/src/components/viewHeader/viewHeaderSearch.tsx b/webapp/src/components/viewHeader/viewHeaderSearch.tsx index f58930e86..00720e1f9 100644 --- a/webapp/src/components/viewHeader/viewHeaderSearch.tsx +++ b/webapp/src/components/viewHeader/viewHeaderSearch.tsx @@ -17,7 +17,7 @@ type Props = { const ViewHeaderSearch = (props: Props) => { const {boardTree, intl} = props - const searchFieldRef = useRef(null) + const searchFieldRef = useRef<{focus(selectAll?: boolean): void}>(null) const [isSearching, setIsSearching] = useState(Boolean(props.boardTree.getSearchText())) const [searchValue, setSearchValue] = useState(boardTree.getSearchText()) diff --git a/webapp/src/widgets/editable.tsx b/webapp/src/widgets/editable.tsx index ed28ddfc6..553eb83d2 100644 --- a/webapp/src/widgets/editable.tsx +++ b/webapp/src/widgets/editable.tsx @@ -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 { - private elementRef = React.createRef() - private saveOnBlur = true +const Editable = (props: Props, ref: React.Ref<{focus: (selectAll?: boolean) => void}>): JSX.Element => { + const elementRef = useRef(null) + const saveOnBlur = useRef(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 ( - ) => { - onChange(e.target.value) - }} - value={value} - title={value} - onBlur={() => this.save('onBlur')} - onKeyDown={(e: React.KeyboardEvent): 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 ( + ) => { + onChange(e.target.value) + }} + value={value} + title={value} + onBlur={() => save('onBlur')} + onKeyDown={(e: React.KeyboardEvent): 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)