I have create a sample react-native app. This app just include TextInput and a Button
export default class App extends Component {
state = {
inputValue: "You can change me!"
};
_handleTextChange = inputValue => {
this.setState({ inputValue });
};
_handleSelectionChange = (event) =>{
this.setState({seleksi : event.nativeEvent.selection});
console.log(event.nativeEvent.selection);
}
_handleButtonPress = () => {
this.setState({inputValue : "Paijo tenan"});
};
render() {
return (
<View style={styles.container}>
<TextInput
value={this.state.inputValue}
onChangeText={this._handleTextChange}
**onSelectionChange={(event)=>this._handleSelectionChange(event)}**
style={{ width: 200, height:200, padding: 8 }}
multiline={true}
/>
<Button
title="Press me"
onPress={this._handleButtonPress}
/>
</View>
);
}
}
when I set onSelectionChange prop, after Button clicked. Text selection on TextInput shows unusual.
Before button clicked, selection shows bullet start and end
After, Selection not show bullet start and end
But when I type some text on TextInput, it's work for selection.
How to make the selection works after I click the button, with onSelectionChange props on TextInput? And why this gonna be happen? how to debug?, my code looks fine
I create expo snack in here https://snack.expo.io/rJ6VxW56x
I finally fixed it! put textinput value like this!
<TextInput ...>
<Text>{this.state.inputValue}</Text>
</TextInput>
I'm not entirely sure if this was your intention... but I found a hacky workaround for ensuring the selection range is the same following button press.
Start by keeping track of selection in the state:
state = {
inputValue: 'You can change me!',
selection: {start: 0, end: 0},
};
Use the selection
prop on TextInput:
selection={this.state.selection}
Ensure you are saving selection to state in _handleSelectionChange
_handleSelectionChange = (event) => {
this.setState({ selection: event.nativeEvent.selection });
}
Modify _handleButtonPress to store selection state before updating inputValue and use the hackish setTimeout to revert the selection after text changes. The reason for the timeout is to give the inputValue time to update which will trigger a _handleSelectionChange which we want to ignore... so we set it to previous value after text changes, selection is the same range as previously and you see the draggable bullets.
_handleButtonPress = () => {
const selectionBeforeChange = { start: this.state.selection.start, end: this.state.selection.end };
this.setState({ inputValue : 'Paijo tenan' }, () => {
setTimeout(() => {
this.setState({ selection: selectionBeforeChange });
}, 50);
});
};
I really dislike using setTimeout anywhere but this solution may work given your needs. A known problem is that if the new text (after button press) is shorter than selection range, it will not properly migrate the previous selection. I'm sure you could check for the new value's length and compare to selection/shorten selection to be a valid selection length if this is your goal.
And, as user Jaws mentions... it is good to be clear where/when you bind your functions to this. I like to bind everything in a constructor to prevent any unnecessary rebinding/keep things together.
constructor(props) {
super(props);
this._handleButtonPress = this._handleButtonPress.bind(this);
this._handleSelectionChange = this._handleSelectionChange.bind(this);
this._handleTextChange = this._handleTextChange.bind(this);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With