Unable to change selected text after changing TextInput value

I've created a sample responsive app. This app just includes 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 click. Selecting text in TextInput shows unusual.

Before pressing the button, the selection shows the start and end of the bullet

Before pressing the button, the selection shows the start and end of the bullet

After that, the selection does not show the start and end of the bullet.

Don't show bullet start and end after selection

But when I type in TextInput, it works for selection.

How do I make the selection work after the button is clicked, with the onSelectionChange props on the TextInput? And why does this happen? how to debug ?, my code looks good

Here I am creating snacks for export https://snack.expo.io/rJ6VxW56x

+3


source to share


3 answers


You can check your event binding for onSelectionChange

. Try the following:



onSelectionChange={this._handleSelectionChange.bind(this)}

      

0


source


I'm not entirely sure if this was your intention ... but I found a hacky solution to ensure that the selection range is the same as when the button is clicked.

Start by tracking the selection in the state:

state = {
  inputValue: 'You can change me!',
  selection: {start: 0, end: 0},
};

      

Use prop selection

in TextInput:

selection={this.state.selection}

      

Make sure you keep the selection in the _handleSelectionChange



_handleSelectionChange = (event) => {
  this.setState({ selection: event.nativeEvent.selection });
}

      

Modify _handleButtonPress to preserve the selection state before updating the inputValue and use the hacky setTimeout to deselect after changing the text. The reason for the timeout is to provide the time to enter the update time, which will trigger _handleSelectionChange, which we want to ignore ... so we changed it to the previous value after changing the text, selecting the same range as before and you see the cartridges being dragged.

  _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 hate using setTimeout anywhere, but this solution might work for your needs. A known issue is that if the new text (after clicking the button) is shorter than the selection range, it will not carry over the previous selection correctly. I'm sure you can check the new value length and compare with the pick / shorten pick to be the valid pick length if that's your goal.

And as user JAWS mentions ... it's good to be clear where / when you link your functions to this. I like to chain everything in the constructor to prevent unnecessary restoring / saving things.

  constructor(props) {
    super(props);
    this._handleButtonPress = this._handleButtonPress.bind(this);
    this._handleSelectionChange = this._handleSelectionChange.bind(this);
    this._handleTextChange = this._handleTextChange.bind(this);
  }

      

0


source


Please make minor changes and give it a try.

Edit

_handleTextChange = inputValue => {
    this.setState({ inputValue });
  };

      

to

_handleTextChange = inputValue => {
    this.setState({ inputValue : inputValue});
  };

      

-2


source







All Articles