mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-25 11:40:04 +08:00
refactor(editable): rewrite with hook (#27655)
* refactor(editable): rewrite with hook * Update Editable.tsx * chore: imrpove * Update Editable.tsx * Update Editable.tsx * Update Editable.tsx
This commit is contained in:
parent
9881be97fd
commit
4b8674d9e9
@ -8,7 +8,7 @@ import { DirectionType } from '../config-provider';
|
||||
|
||||
interface EditableProps {
|
||||
prefixCls?: string;
|
||||
value?: string;
|
||||
value: string;
|
||||
['aria-label']?: string;
|
||||
onSave: (value: string) => void;
|
||||
onCancel: () => void;
|
||||
@ -19,107 +19,7 @@ interface EditableProps {
|
||||
autoSize?: boolean | AutoSizeType;
|
||||
}
|
||||
|
||||
interface EditableState {
|
||||
current: string;
|
||||
prevValue?: string;
|
||||
}
|
||||
|
||||
class Editable extends React.Component<EditableProps, EditableState> {
|
||||
static getDerivedStateFromProps(nextProps: EditableProps, prevState: EditableState) {
|
||||
const { prevValue } = prevState;
|
||||
const { value } = nextProps;
|
||||
const newState: Partial<EditableState> = {
|
||||
prevValue: value,
|
||||
};
|
||||
|
||||
if (prevValue !== value) {
|
||||
newState.current = value;
|
||||
}
|
||||
|
||||
return newState;
|
||||
}
|
||||
|
||||
textarea?: TextArea;
|
||||
|
||||
lastKeyCode?: number;
|
||||
|
||||
inComposition?: boolean = false;
|
||||
|
||||
state = {
|
||||
current: '',
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
if (this.textarea && this.textarea.resizableTextArea) {
|
||||
const { textArea } = this.textarea.resizableTextArea;
|
||||
textArea.focus();
|
||||
const { length } = textArea.value;
|
||||
textArea.setSelectionRange(length, length);
|
||||
}
|
||||
}
|
||||
|
||||
onChange: React.ChangeEventHandler<HTMLTextAreaElement> = ({ target: { value } }) => {
|
||||
this.setState({ current: value.replace(/[\n\r]/g, '') });
|
||||
};
|
||||
|
||||
onCompositionStart = () => {
|
||||
this.inComposition = true;
|
||||
};
|
||||
|
||||
onCompositionEnd = () => {
|
||||
this.inComposition = false;
|
||||
};
|
||||
|
||||
onKeyDown: React.KeyboardEventHandler<HTMLTextAreaElement> = ({ keyCode }) => {
|
||||
// We don't record keyCode when IME is using
|
||||
if (this.inComposition) return;
|
||||
|
||||
this.lastKeyCode = keyCode;
|
||||
};
|
||||
|
||||
onKeyUp: React.KeyboardEventHandler<HTMLTextAreaElement> = ({
|
||||
keyCode,
|
||||
ctrlKey,
|
||||
altKey,
|
||||
metaKey,
|
||||
shiftKey,
|
||||
}) => {
|
||||
const { onCancel } = this.props;
|
||||
// Check if it's a real key
|
||||
if (
|
||||
this.lastKeyCode === keyCode &&
|
||||
!this.inComposition &&
|
||||
!ctrlKey &&
|
||||
!altKey &&
|
||||
!metaKey &&
|
||||
!shiftKey
|
||||
) {
|
||||
if (keyCode === KeyCode.ENTER) {
|
||||
this.confirmChange();
|
||||
} else if (keyCode === KeyCode.ESC) {
|
||||
onCancel();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
onBlur: React.FocusEventHandler<HTMLTextAreaElement> = () => {
|
||||
this.confirmChange();
|
||||
};
|
||||
|
||||
confirmChange = () => {
|
||||
const { current } = this.state;
|
||||
const { onSave } = this.props;
|
||||
|
||||
onSave(current.trim());
|
||||
};
|
||||
|
||||
setTextarea = (textarea: TextArea) => {
|
||||
this.textarea = textarea;
|
||||
};
|
||||
|
||||
render() {
|
||||
const { current } = this.state;
|
||||
const {
|
||||
const Editable: React.FC<EditableProps> = ({
|
||||
prefixCls,
|
||||
'aria-label': ariaLabel,
|
||||
className,
|
||||
@ -127,7 +27,81 @@ class Editable extends React.Component<EditableProps, EditableState> {
|
||||
direction,
|
||||
maxLength,
|
||||
autoSize,
|
||||
} = this.props;
|
||||
value,
|
||||
onSave,
|
||||
onCancel,
|
||||
}) => {
|
||||
const ref = React.useRef<any>();
|
||||
|
||||
const inComposition = React.useRef(false);
|
||||
const lastKeyCode = React.useRef<number>();
|
||||
|
||||
const [current, setCurrent] = React.useState(value);
|
||||
|
||||
React.useEffect(() => {
|
||||
setCurrent(value);
|
||||
}, [value]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (ref.current && ref.current.resizableTextArea) {
|
||||
const { textArea } = ref.current.resizableTextArea;
|
||||
textArea.focus();
|
||||
const { length } = textArea.value;
|
||||
textArea.setSelectionRange(length, length);
|
||||
}
|
||||
}, [ref.current]);
|
||||
|
||||
const onChange: React.ChangeEventHandler<HTMLTextAreaElement> = ({ target }) => {
|
||||
setCurrent(target.value.replace(/[\n\r]/g, ''));
|
||||
};
|
||||
|
||||
const onCompositionStart = () => {
|
||||
inComposition.current = true;
|
||||
};
|
||||
|
||||
const onCompositionEnd = () => {
|
||||
inComposition.current = false;
|
||||
};
|
||||
|
||||
const onKeyDown: React.KeyboardEventHandler<HTMLTextAreaElement> = ({ keyCode }) => {
|
||||
// We don't record keyCode when IME is using
|
||||
if (inComposition.current) return;
|
||||
|
||||
lastKeyCode.current = keyCode;
|
||||
};
|
||||
|
||||
const confirmChange = () => {
|
||||
onSave(current.trim());
|
||||
};
|
||||
|
||||
const onKeyUp: React.KeyboardEventHandler<HTMLTextAreaElement> = ({
|
||||
keyCode,
|
||||
ctrlKey,
|
||||
altKey,
|
||||
metaKey,
|
||||
shiftKey,
|
||||
}) => {
|
||||
// Check if it's a real key
|
||||
if (
|
||||
lastKeyCode.current === keyCode &&
|
||||
!inComposition.current &&
|
||||
!ctrlKey &&
|
||||
!altKey &&
|
||||
!metaKey &&
|
||||
!shiftKey
|
||||
) {
|
||||
if (keyCode === KeyCode.ENTER) {
|
||||
confirmChange();
|
||||
} else if (keyCode === KeyCode.ESC) {
|
||||
onCancel();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const onBlur: React.FocusEventHandler<HTMLTextAreaElement> = () => {
|
||||
confirmChange();
|
||||
};
|
||||
|
||||
const textAreaClassName = classNames(
|
||||
prefixCls,
|
||||
`${prefixCls}-edit-content`,
|
||||
@ -136,25 +110,25 @@ class Editable extends React.Component<EditableProps, EditableState> {
|
||||
},
|
||||
className,
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={textAreaClassName} style={style}>
|
||||
<TextArea
|
||||
ref={this.setTextarea}
|
||||
ref={ref as any}
|
||||
maxLength={maxLength}
|
||||
value={current}
|
||||
onChange={this.onChange}
|
||||
onKeyDown={this.onKeyDown}
|
||||
onKeyUp={this.onKeyUp}
|
||||
onCompositionStart={this.onCompositionStart}
|
||||
onCompositionEnd={this.onCompositionEnd}
|
||||
onBlur={this.onBlur}
|
||||
onChange={onChange}
|
||||
onKeyDown={onKeyDown}
|
||||
onKeyUp={onKeyUp}
|
||||
onCompositionStart={onCompositionStart}
|
||||
onCompositionEnd={onCompositionEnd}
|
||||
onBlur={onBlur}
|
||||
aria-label={ariaLabel}
|
||||
autoSize={autoSize === undefined || autoSize}
|
||||
/>
|
||||
<EnterOutlined className={`${prefixCls}-edit-content-confirm`} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default Editable;
|
||||
|
Loading…
Reference in New Issue
Block a user