Skip to content

Instantly share code, notes, and snippets.

@syJSdev
Created October 28, 2020 01:30
Show Gist options
  • Select an option

  • Save syJSdev/da0e7ecec6a154d1beb2d0c31bb76f15 to your computer and use it in GitHub Desktop.

Select an option

Save syJSdev/da0e7ecec6a154d1beb2d0c31bb76f15 to your computer and use it in GitHub Desktop.
Input component wrapper to prevent cursor jump
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