2018年4月27日金曜日

react native0.54.2以降でTextInputでonChangeTextを使うと日本語変換ができなくなる的なお話

  • このエントリーをはてなブックマークに追加

まんまタイトル通り。
https://github.com/facebook/react-native/pull/18456
valueもしくはdefaultValueとして値を入れてかつonChangeTextを使うと日本語の変換ができなくなる。
なんか望ましくない文字を入れたくないためのアップデートらしい。

とりあえずこのままだと困るので、今日はこれを対処するお話をば。

ちなみにExpo30(2018/09/13)とReact Native0.57以降ではこの問題修正されてるので気にせずで大丈夫的な。

<TextInput value={this.state.value} onTextInput={(e) => this.setState({value:e.nativeEvent.text})} />

onTextInputを使えばいい。
https://github.com/facebook/react-native/blob/a3a98eb1c7fa0054a236d45421393874ce8ce558/Libraries/Components/TextInput/TextInput.js#L1049
ちなみにこれは公式ドキュメントには載っていないので知らなかった。

ということでonTextInputを使えば日本語変換ちゃんとできるよ的な。
こういう仕様変更されるとバージョンをアップした瞬間にちゃんと動作しなくなるとかあるから要注意だよね的なみたいな。

違う解決方法(追記:2018/05/06)

valueをstateで管理していると日本語変換ができないわけで。
けどプロフィール編集画面を作るとかだとstateで初期値が入れておきたいということもあるわけで。
だからこんな感じでやれば大丈夫。

shouldComponentUpdate(nextProps,nextState){
  if(this.state.value !== nextState.value){
    return false;
  }

  return true;
}

<TextInput value={this.state.value} onChangeText={text => this.setState({value:text})} />

うまく説明できないんだけど、これで今までと同じようにちゃんと日本語変換できるようになる。
shouldComponentUpdateの中で分岐とか面倒だから、TextInputのコンポーネントを作ると楽になるかと。

ちなみにsnackはこれ。
https://snack.expo.io/Hkp55vn6G

さらに追記(追記:2018/05/06)

コメントで指摘されているように、this.inputRef.clear()や渡されるvalueに空を代入してテキストボックスを空にしたいときがあるが、
自分が出した手法ではそれらは出来ないので、さらにcomponentDidUpdateを使うなりして解決する方法がある。
gistはこちらから。

componentDidUpdate(prevProps) {
  if (prevProps.value !== this.props.value && this.props.value === '') {
    this.setState({ value: '', refresh: true }, () => this.setState({ refresh: false }));
  }
}

render() {
  if (this.state.refresh) {
    return null;
  }

return (
    <Input
      {...this.props}
      ref={(ref) => { this.input = ref; }}
      value={this.state.value}
    />
  );
}

propsのvalueに''が代入された際に、stateとしてrefresh = trueとする。
そうすると一度nullがレンダリングされ、setStateのコールバックとしてrefresh = falseとすることでTextInputが再びレンダリングされる。
かなり強引な手法ではあるが。

ただthis.inputRef.clear()をする方法はちょっと見つけられなかった。

正直なところ、次のバージョンなりで修正されていることを願うしかないのかなと。

Adsense