Created
October 28, 2020 01:30
-
-
Save syJSdev/da0e7ecec6a154d1beb2d0c31bb76f15 to your computer and use it in GitHub Desktop.
Input component wrapper to prevent cursor jump
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import React, { useState, useRef, useEffect } from 'react'; | |
| import PropTypes from 'prop-types'; | |
| function useRunAfterUpdate() { | |
| const afterPaintRef = React.useRef(null); | |
| React.useLayoutEffect(() => { | |
| if (afterPaintRef.current) { | |
| afterPaintRef.current(); | |
| afterPaintRef.current = null; | |
| } | |
| }); | |
| // eslint-disable-next-line no-return-assign | |
| return fn => (afterPaintRef.current = fn); | |
| } | |
| const InputBox = React.memo(({ onChange, value, ...props }) => { | |
| const [localValue, setLocalValue] = React.useState(''); | |
| const runAfterUpdate = useRunAfterUpdate(); | |
| const input = useRef(); | |
| const inputStart = useRef(); | |
| function handleChange(e) { | |
| input.current = e.target; | |
| inputStart.current = input.current.selectionStart; | |
| onChange(e); | |
| } | |
| useEffect(() => { | |
| setLocalValue(value); | |
| runAfterUpdate(() => { | |
| if (input.current && inputStart.current) { | |
| input.current.selectionStart = inputStart.current; | |
| input.current.selectionEnd = inputStart.current; | |
| } | |
| }); | |
| }, [value, runAfterUpdate]); | |
| return <input {...props} value={localValue} onChange={handleChange} />; | |
| }); | |
| InputBox.propTypes = { | |
| value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), | |
| onChange: PropTypes.func.isRequired, | |
| }; | |
| export default InputBox; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment