LoginSignup
6
4

More than 3 years have passed since last update.

FlutterでstatelessなTextFieldを作ったので宣伝したい

Posted at

はじめに

FlutterやReactにおいて、大きな関心ごとの一つに状態管理がある。
TextFieldはその性質上、自ら状態を持つ設計になりやすい。
しかし、TextFieldの入力情報をcallbackで返し、TextFieldの引数に現在値を与えることでTextFieldが状態を持たないようにできる。
ユースケースはProviderなどの状態管理ツールを入れているプロジェクトに限定されると思うが、私が欲しいと思ったので、今回作成した。
ついでに勉強がてら公開してみた。

メリット

  • TextFiledの状態を自前で管理できるようになる(Provider, redux, Reverpod, BLoc, etc...)
  • 他のwidgetの状態と連動させやすい

デメリット

  • 自前で状態管理するコードを書く必要がある
  • rebuildのタイミングを把握していないと、文字列入力中にwidgetがrebuildされ、文字が消えることがある

先行記事

Flutterにおける状態管理は様々な手法がある。こちらの記事が非常によくまとまっていると感じた。
この記事では状態管理方法については言及せず、外側で状態管理をしやすいTextFieldについて記述する。

こちらの記事と全く目的が同じである。
しかし、こちらの記事では状態管理を完全に外だししているわけではなく、Stateに状態を持たせてしまっているため、外からTextFieldに表示したい文字列を与えても変化しない課題がある。
WidgetとStateの関係についてはこちらの記事がとても参考になった。

使い方

こちらのリポジトリに公開している。
また、pub.devにも公開している。

exampleを見てもらうのが一番早いが、こちらにもコードを載せておく。
githubやpub.devが最新版となるため、そこはご了承を...

class _MyHomePageState extends State<MyHomePage> {
  String _message = "";

  void _setMessage(String str) =>
      setState(() => _message = str);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            StatelessTextField(
              initialValue: _message,
              style: Theme.of(context).textTheme.headline4,
              decoration: InputDecoration(hintText: "first message field"),
              onSubmitted: _setMessage,
            ),
            StatelessTextField(
              initialValue: _message,
              style: Theme.of(context).textTheme.headline6,
              decoration: InputDecoration(hintText: "second message field"),
              onSubmitted: _setMessage,
            )
          ],
        ),
      ),
    );
  }
}

簡単に説明すると、縦に並ぶ二つのStatelessTextFieldinitialVlaue_messageを与えて、onSubmitted_messageを更新してrebuildするexampleである。
このようにStatelessTextFieldは外側で状態管理をしたいときに有効である。

実装(使うだけなら知らなくてもOK)

TextFieldに初期値を与えるためには、TextEditControllerを保持しなければならないため、やむなくStatefulWidgetをextendsして作成した。
が、使用感はStatelessWidgetなので、stateless_textfieldと命名した。

exampleのような構成ではkeyを正しく与えないとWidgetとStateの組み合わせがずれてしまう場合があると思うが、Stateに状態を持たない構成なので、ずれてしまっても問題ない。
なんとなく気持ち悪いと思うが、悪影響はなさそうなので、このような実装にした。

TextEditControllerが曲者

TextFieldに初期値を与えるためにはTextEditControllerを用意しなければならない。
また、これはちゃんとdispose()を呼ばないとメモリリークする危険物であるため、そのハンドリングのためにStateで保持している。
逆に言えば、Stateで保持しているのはこれだけである。(たまにちゃんとdisposeしていないサンプルを見かけるが、大丈夫なのだろうか...)

最後に

Flutterの勉強を初めて半月くらいですが、WidgetとElementの関係や、公式の提供するWidgetの豊富さが面白く、「Flutter凄いー」となっています。
フロントエンドを例えに出すとReact + Material-UIといった感じですね。サクサク作れます。
Flutterの勉強がてら、自分用のflutter_templateを作っていたところ、状態を持たないTextFieldが欲しくなったので作りました。

6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4