Reputation: 12819
The cursor keeps going to the end. How to keep the cursor position when editing from the the middle of the string?
Code that I am using is:
const rootElement = document.getElementById('root');
class MyFancyForm extends React.Component {
constructor(props) {
super(props);
this.state = {myValue: ""};
}
handleCommaSeparatedChange = event => {
const {value} = event.target;
this.setState({myValue: value});
};
render() {
return(
<form >
<div>
<label>
Cursor position looser
<br />
<input onChange={this.handleCommaSeparatedChange} value={this.state.myValue} />
</label>
</div>
</form>
)
}
}
const element = <MyFancyForm />;
ReactDOM.render(element, rootElement);
Any idea how could I achieve it?
Upvotes: 29
Views: 20480
Reputation: 618
I solved this by creating a TextInput
component that wraps <input type="text">
and proxying the value in internal state.
function TextInput({ value, onChange }) {
// Create a proxy value in internal state to prevent the caret from jumping to the end every time the value updates
const [currentValue, setCurrentValue] = useState<string>(value);
useEffect(() => {
setCurrentValue(value);
}, [value]);
return (<input
type="text"
value={currentValue}
onChange={(e) => {
setCurrentValue(e.target.value);
onChange(e.target.value);
}}
/>);
}
Then I use it in a parent component like so. It works well so far.
<TextInput
value={textValue}
onChange={(e) => {
setTextValue(e);
}}
/>
Upvotes: 4
Reputation: 1599
I know it's an old post but this might help someone.
I found this snippet in one github issue and helped me to get around this problem.
onChange={(event) => {
event.persist()
const caretStart = event.target.selectionStart;
const caretEnd = event.target.selectionEnd;
// update the state and reset the caret
this.updateState();
event.target.setSelectionRange(caretStart, caretEnd);
}}
Quote from: https://github.com/facebook/react/issues/955#issuecomment-469344232
Upvotes: 3
Reputation: 343
just change value
into defaultValue
- it worked both in codepen and codesandbox for me
class MyFancyForm extends React.Component {
constructor(props) {
super(props);
this.state = {myValue: ""};
}
handleCommaSeparatedChange = event => {
const {value} = event.target;
this.setState({myValue: value});
};
render() {
return(
<form >
<div>
<label>
Cursor position looser
<br />
<input onChange={this.handleCommaSeparatedChange} defaultValue={this.state.myValue} />
</label>
</div>
</form>
)
}
}
ReactDOM.render(
<MyFancyForm />,
document.getElementById('root')
);
Upvotes: 16