Lean Engineer

リーンエンジニア〜効率的に実験しながら、技術を学ぶブログ

ReactNative 0.56(0.54以上)でiOSの日本語入力の変換が動かない問題

 「人狼ゲームマスター」という人狼ゲームのゲームマスターをやってくれる、超絶便利なアプリ(自画自賛)を作っているのだが、ReactNativeを0.53からアップデートしたら、iOSですごくバグって困った。ご不便おかけしました。ちなみに、Androidでは同問題は起こっていない。

 何が困ったって、日本語入力の変換ができないこと。変換が効かないので、小文字や濁点すら打てない。もちろん、予想変換も動かない。人狼ゲームのプレイヤーの名前を入力するところに、TextInputを使っていたので僕の名前の「じぇい」は「しえい」としか入力できなかった笑

 さて、本家ReactNativeのリポジトリでissueは上がっているのだが、0.54で問題が発生し、現在0.56がリリースされているが、まだ治ってない。困った。

 で、別のissueのコメントで、良さそうな修正案が提案されているが、ある程度はこれで上手くいく。しかし、この方法だと、ちょっと困ったことがある。

  • refを使って、clearすることができない
  • 並び替えなどの再レンダリングのときに、表示が変わらない

 などである。人狼ゲームマスターでは、並び替えがウリなのに、これができないのはツライ。で、いろいろ試行錯誤した結果、入力中のprops.valueにdiffがある場合のみ、shouldComponentUpdatefalseで返せば良い。つまり、上記issueの修正案に、入力中のフラグをもたせてあげれば良い。ちょっと無理やりだが、以下で上手く動いているようだ。

import React from 'react'
import { Platform, TextInput as Input } from 'react-native'

export default class TextInput extends React.Component {
  state = {
    editing: false
  }
  static defaultProps = {
    onFocus: () => { },
    onEndEditing: () => { },
  }
  shouldComponentUpdate(nextProps) {
    return Platform.OS !== 'ios' || !this.state.editing || this.props.value === nextProps.value
  }

  render() {
    return (
      <Input
        {...this.props}
        onFocus={() => {
          this.props.onFocus()
          this.setState({ editing: true })
        }}
        onEndEditing={() => {
          this.props.onEndEditing()
          this.setState({ editing: false })
        }}
      />
    );
  }
}

 本当は、refをとってisFocusedにしたかったんだけど、なんだか上手く動かなかったので、あえなくonFocusonEndEditingstateを変更するという力技にしている。

 ふーむ。早くReactNative側で治して欲しい。

 この修正が上手く動かない場合は、0.53.xにダウングレードしないといけないのだが、それはそれでパフォーマンスが悪化したり、Androidで予想変換で絵文字入力するとクラッシュするなどの問題が再発することになる。今の所、上手く動いてそうなので、僕は上記のコードを使っている。