Reactで行数可変なtextareaを作った話
TL;DR
中身に応じて高さが変わるtextareaが出来た
コピペ、複数行まとめて削除しても大丈夫
軽く検索しても出てこなかったので
似たようなことをしたくなった人や未来の自分のために書いてみました
環境
react:15.6.2
redux-form:6.8.0
lodash.isempty:4.4.0
正直reactだけでもOKなはず
廃止されるライフサイクルメソッドなども使っていないので最新版のreactでも動くと思います
他2つは細かいところ書くのが面倒なので使ってます
無くても本質には関係ないので大丈夫です
chromeとIEで動作確認済み(バージョンはわからないですが2020/01付近です)
参考
実装
細かいところはフィーリングで読んでください
import React from 'react';
import { Field, reduxForm } from 'redux-form';
import TextArea from './textArea';
function index() {
return (
<div>
<Field name="TextArea" component={TextArea} rows={2} />
</div>
)
}
export default reduxForm({ form: 'form' })(index);
import React, { Component } from 'react';
import isEmpty from 'lodash.isempty';
class TextArea extends Component {
constructor(props) {
super(props);
this.textArea = null;
}
shouldComponentUpdate(nextProps) {
if (this.props.input.value !== nextProps.input.value) {
if (isEmpty(nextProps.input.value)) {
this.textArea.setAttribute('rows', this.props.rows);
} else {
this.textArea.setAttribute('rows', this.props.rows);
while (this.textArea.scrollHeight > this.textArea.offsetHeight) {
const tempRows = Number(this.textArea.getAttribute('rows'));
this.textArea.setAttribute('rows', tempRows + 1);
}
}
}
return true;
}
render() {
return (
<textarea
ref={c => {
this.textArea = c;
}}
style={{ resize: 'none' }}
name={this.props.input.name}
onChange={e => this.props.input.onChange(e.target.value, this.props.input.name)}
rows={this.props.rows}
/>
);
}
}
解説
参考にしたコードと似たようなことをしています
以下の部分が全てです
shouldComponentUpdate(nextProps) {
// textareaの内容が変更された時のみ操作
if (this.props.input.value !== nextProps.input.value) {
if (isEmpty(nextProps.input.value)) {
// 内容が空なら初期値の行数に戻すだけ
this.textArea.setAttribute('rows', this.props.rows);
} else {
this.textArea.setAttribute('rows', this.props.rows);
// 内容が有るならスクロールせずに表示できる高さになるまで初期値から1行ずつ増やす
while (this.textArea.scrollHeight > this.textArea.offsetHeight) {
const tempRows = Number(this.textArea.getAttribute('rows'));
this.textArea.setAttribute('rows', tempRows + 1);
}
}
}
return true;
}
注意点
高さにmax-heightなどで上限を定めたい時は
直接textareaにmax-heightを書かないでください
高さの計算とぶつかるのか無限ループになってブラウザが固まります
高さを決めたい場合は適当にラップしてそちらに色々設定してください
※今回で言うと、index.jsのdivに{max-height: 100px, overflow-y: scroll}みたいにすれば
100pxより入力欄が高くなったらスクロールになるよう切り替えられます
まとめ
shouldComponentUpdateでこういうことして良いのかはわかりませんがとりあえず動いてるのでヨシとします
横方向(cols)にも同じ方法で拡縮できるのではないかと思いますがそこまでは試してないです
Author And Source
この問題について(Reactで行数可変なtextareaを作った話), 我々は、より多くの情報をここで見つけました https://qiita.com/john_skm/items/6b97a51f55e857a1adc8著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .