In react-native TextInput is always autoexpandable. See https://github.com/facebook/react-native/commit/dabb78b1278d922e18b2a84059460689da12578b
I think simplest way to implement this is to use https://github.com/rpearce/react-expanding-textarea
It's just update textarea height based on el.scrollHeight:
_handleChange(e) {
const { onChange } = this.props
if (onChange) onChange(e)
this._adjustTextarea(e)
}
_adjustTextarea({ target = this.el }) {
target.style.height = 0
target.style.height = `${target.scrollHeight}px`
}
}
@gut4 There is a problem with such an implementation. It will break the window scroll occasionally. It's probably much harder to implement with fake height placeholder etc. I had to switch to contentEditable.
Here is how you do it:
import React, { useState } from 'react';
import { TextInput } from 'react-native';
export default function TextField(props) {
const [scrollHeight, setScrollHeight] = useState(null);
return (
<TextInput
style={{ height: scrollHeight }}
onChange={(e) => setScrollHeight(e.target.scrollHeight)}
{...props}
/>
);
}
@woodpav This with multiline works great to increase the size of the text input, but it unfortunately doesn't shrink it when you remove text.
Using the solution proposed by @gut4 worked in both direction for me.
import * as React from 'react';
import { TextInput } from 'react-native';
export default function App() {
const _handleChange = (e) => {
e.target.style.height = 0
e.target.style.height = `${e.target.scrollHeight}px`
};
return (
<TextInput
multiline
onChange={_handleChange}
/>
);
}
I'm curious if this approach translates across platforms, i.e. can we rely on scrollHeight to be exposed and updated immediately when e.target.style.height is set to zero? My approach is slightly more involved, measuring a hidden Text element to detect shrinking heights, i.e.:
const [height, setHeight] = useState(props.initialHeight);
return(
<View>
<TextInput
{...props}
style={[props.style, {height: height}]}
onContentSizeChange={e => setHeight(e.nativeEvent.contentSize.height)}
/>
<Text
onLayout={e => e.nativeEvent.layout.height < height && setHeight(e.nativeEvent.layout.height)}
style={[props.style, {position: 'absolute', visibility: 'hidden'}]}
pointerEvents={'none'}
>
{`${props.value || props.defaultValue || props.placeholder ||聽''}\n`}
</Text>
</View>
)
@necolas Are there any plans getting this natively supported by react native web at some point?
Could we use https://www.npmjs.com/package/react-textarea-autosize or a similar approach to get closer to the behaviour of the iOS/Android counterparts of TextInput with multiline enabled?
Most helpful comment
Here is how you do it: