みかづきブログ・カスタム

基本的にはちょちょいのほいです。

Reactでテキストエリアに行数制限を実装を試みる 📝

https://cdn-ak.f.st-hatena.com/images/fotolife/k/kimizuka/20210416/20210416093201.png


テキストエリアに行数制限を作りたくてもろもろ検討しました。
日本語だけの対応でOKであれば、当幅フォントを使って行も列も制限を掛けるのが良いと思いました。

DEMO


  1. フォントサイズを10pxに設定
  2. リサイズを不可に設定
  3. 大きさを20文字×10行に合わせる
  4. 最大10行までしか入力できないよう制限
  5. 1列は最大20文字しか入力できないよう制限
  6. つまり、20文字 × 10行の200文字が最大入力数

という感じで実装してみました。
テキストエリアの右側にはCanvasで作ったプレビューを表示しています。

  1. 半角の入力があると10行まで到達しない(プレビューは10行になる)
  2. 10行、または200文字を超える文字がペーストできない
  3. 行数が最大値の際に文章の途中を編集しようとすると、カーソルが最後尾に移動するのが使いにくい


という問題があるので、まだまだ実践投入はできませんが、引き続きベストプラクティスを探っていこうと思います。


JavaScript

const { useRef, useState } = React;

const fontSize = 10;
const maxCols = 20;
const maxRow = 10;

function App() {
  const textAreaRef = useRef(null);
  const [ value, setValue ] = useState('');

  function handleChangeTextarea() {
    const list = [[]];
    const value = textAreaRef.current.value;

    [...value].forEach((txt) => {
      if (txt !== '\n') {
        if (list[list.length - 1].length < maxCols) {
          list[list.length - 1].push(txt);
        } else {
          list.push([txt]);
        }
      } else {
        list.push([]);
      }
    });

    if (list.length <= maxRow) {
      setValue(value);
    }
  }

  return (
    <textarea
      autoComplete="off"
      cols={ maxCols }
      onChange={ handleChangeTextarea }
      rows={ maxRow }
      ref={ textAreaRef }
      style={{ fontSize: `${ fontSize }px` }}
      value={ value }
      wrap="hard"
    ></textarea>
  );
}

ReactDOM.render(
  React.createElement(App),
  document.getElementById('app')
);