Oliver Franke Oliver Franke - 2 months ago 22
Javascript Question

React Native add text to TextInput on button click

I would like to create a search field within React Native which works somehow similar to the searchfield on my webpage https://todayin.de/ .

What I did so far is the following:

class SearchField extends React.Component {
constructor(props){
super(props);
this.state = {text: ''};
this.U9 = '#U9';
}
render() {
return(
<View>
<TextInput
autoCorrect={false}
autoFocus={false}
placeholder="#Kicker #Moabit"
onChangeText={(text) => this.setState({text})}
value={this.state.text}
onSubmitEditing={(event) => this.startSearch()}
/>

<Button
style={{fontSize: 20, color: 'green'}}
styleDisabled={{color: 'red'}}
onPress={this.addTagToInput.bind(this)}
>
{this.U9}
</Button>

</View>

);
}
startSearch(){
alert(this.state.text);
}
addTagToInput(event){
this.state = {text: this.state.text + " " + this.U9};
}

}
module.exports = SearchField;


When I enter a search text to the TextInput it works fine and is shown in alert() on submit. What I want to achieve now is, when I click on the button "#U9", I want to append the string #U9 to the text input and display it. Right now if I enter the text "test", click the "#U9" button and submit, I get "test #U9" alerted as I expect.
The problem is, that the #U9 is not displayed in the input field. How can I update the text input when I click the button?

For the finetuning I would like to add buttons and according values in a foreach to avoid repeating 10 times the same code. If any1 has a suggestion for that as well I would love to hear it!

For the very very finetuning I would like to do the following:
On first button click: append #U9 to the text.
On second button click: remove #U9 from the text.

Thanks a lot for some help!

Cheers,
Oliver

Answer Source

You're just re-assigning the state field, rather than calling setState. Try

addTagToInput(event){
    this.setState({text: this.state.text + " " + this.U9});
}

React uses setState to reassign the state field and to notify the framework that this component needs to rerender

See setState documentation

edit: First thing to do is to move the button's render logic into it's onw function and to update the event handler to take the tag name as a param

renderButton(tag){
  return (<Button   
        style={{fontSize: 20, color: 'green'}}
        styleDisabled={{color: 'red'}}
        onPress={this.addTagToInput.bind(tag)}>
        {tag}
      </Button>);
}
addTagToInput(tag){
    this.setState({text: this.state.text + " " + tag});
}

Then replace the U9 varialbe with a list of tags

constructor(props){
    super(props);
    this.state = {text: ''};
    this.tags = ['#U9'];
}

And replace the normal button rendering code with a map over the tags

render() {
    return(
        <View>
        <TextInput 
        autoCorrect={false}
        autoFocus={false} 
        placeholder="#Kicker #Moabit"
        onChangeText={(text) => this.setState({text})}
        value={this.state.text}
        onSubmitEditing={(event) => this.startSearch()}
        />
        {this.tags.map(this.renderButton)}
        </View>

        );
}

This will render all the tags as buttons and pass their value into the event handler