14

I want to create a TextInput which can grow automatically when it has multilines.

 <TextInput
            placeholder="Type Comment"
            value={this.state.comment.value}
            onChangeText={value => this.onChangeComment(value)}
            onPress={() => this.uploadComment()}
            multiline={true}
            maxLength={200}
            numberOfLines={5}
          />

How can I achieve this?

Shashika Virajh
  • 8,497
  • 17
  • 59
  • 103

5 Answers5

13

Think that the React Native team fixed it in current version (0.59) with the multiline prop.

This works for me

  <TextInput
    style={{
      width: '90%',
      borderColor: 'gray',
      borderWidth: 1,
      padding: 2,
    }}
    multiline
    onChangeText={text => this.setState({ text })}
    value={this.state.text}
  />
Norfeldt
  • 8,272
  • 23
  • 96
  • 152
  • How would one do this using functional components? – ahron Feb 14 '22 at 18:08
  • 1
    You do a 'const [text, setText] = React.useState' followed by 'const onChangeTextHandler = React.useCallback(text => setText(text),[setText])' and then you do the prop like 'onChangeText={onChangeTextHandler}' – Norfeldt Feb 14 '22 at 18:22
  • 1
    And 'value={text}' for the last prop – Norfeldt Feb 14 '22 at 18:23
11

To implement auto grow multiline text input, you can adjust the height of the text input according to the content size in the textInput.

you can use onContentSizeChange prop in TextInput and call a function to increase/decrease the height of input.

Here is the quick example code

export default class YourComponent extends Component {

  constructor (props) {
    super(props);
    this.state = {
      newValue: '',
      height: 40
    }
  }

  updateSize = (height) => {
    this.setState({
      height
    });
  }

  render () {
    const {newValue, height} = this.state;

    let newStyle = {
      height
    }

    return (
    <TextInput
      placeholder="Your Placeholder"
      onChangeText={(value) => this.setState({value})}
      style={[newStyle]}
      editable
      multiline
      value={value}
      onContentSizeChange={(e) => this.updateSize(e.nativeEvent.contentSize.height)}
    />
    )
  }

}  

OR

You might want to use react-native-auto-grow-textinput

Toastrackenigma
  • 7,604
  • 4
  • 45
  • 55
Shivam
  • 3,091
  • 4
  • 30
  • 45
  • 1
    I tried this solution, but onContentSizeChange fires on initial render and sets a different height for me. Don't understand why – monchisan Jan 13 '20 at 12:30
6

With React Hooks

Just to add to Shivam's answer, here is the version with hooks:

import React, { useState } from 'react'

export default function MyTextInput(props) {
    const [height, setHeight] = useState(42)
    return <TextInput
        style={styles.input, {height: height}}
        onContentSizeChange={e => setHeight(e.nativeEvent.contentSize.height)} />
}
Andrei
  • 42,814
  • 35
  • 154
  • 218
  • Could you please look into this : https://stackoverflow.com/questions/74456363/alignitems-flex-end-not-working-with-oncontentsizechange – user2028 Nov 28 '22 at 13:16
1

Use module for this

import {AutoGrowingTextInput} from 'react-native-autogrow-textinput';

return (
  <AutoGrowingTextInput 
    style={styles.textInput} 
    placeholder={'Your Message'}
    value={value}
  />
)

Link: https://www.npmjs.com/package/react-native-autogrow-textinput

0

For anyone else wondering how to have it grow AND shrink by new lines here's what I did.

const [text,setText] = useState('');
const [textHeight,setTextHeight = useState(35);
    
<TextInput
   style={{height:textHeight,maxHeight:200}}
   value={text}
   multiline
   onChangeText={(e)=>{
      setText(e);
      setTextHeight(35 + (e.split('\n').length-1) * 20);
   }}
/>