React Native 中 TextInput 組件和中文輸入沖突

在用 React Native (下稱 RN) 開發(fā)面向國人的應(yīng)用時,不可避免會有用戶使用中文輸入法的情景。在 RN 中,負(fù)責(zé)輸入內(nèi)容的控件是 <TextInput>,但這個組件有一個截止至 0.41.2 版本都還存在的中文顯示 bug。類似的行為在使用英文輸入法時并不會出現(xiàn),所以我在 GitHub 提交了一個沒人理的 issue #12599

復(fù)現(xiàn)

完整最小化復(fù)現(xiàn)代碼在這里?,F(xiàn)在只展示 render() 中代碼,用于最小化復(fù)現(xiàn),新建一個項(xiàng)目后修改 index.ios.js 即可。

render () {
  return (
    <View style={styles.container}>
      <TextInput
        style={styles.inputField}
        value={this.state.text}
        placeholder="Type here to translate!"
        onChangeText={(text) => this.setState({ text })} />
      <Text style={styles.previewText}>
        {this.state.text}
      </Text>
      <TextInput style={styles.inputField} placeholder="Another to focus, meaningless" />
    </View>
  );
}

猜測原因

這個問題一開始確實(shí)比較令人費(fèi)解,但用一個 <Text> 組件顯示了 this.state 內(nèi)部的內(nèi)容后,發(fā)現(xiàn)了問題可能存在部分—— <Text> 中的文本來源于 this.state.text,而在輸入框中文本消失后,<Text> 中的文本并沒有一起消失,即我們應(yīng)該是成功的設(shè)置了 this.state.text 的內(nèi)容,但出于某些原因,輸入框的顯示有一些問題。

嘗試為各個可能涉及更新 this.state 操作的 props 增加了回調(diào)用于輸出 this.state 內(nèi)容。操作和 console 中輸出的結(jié)果如動圖。

repro2
repro2
render () {
  return (
    <View style={styles.container}>
      <TextInput
        style={styles.inputField}
        value={this.state.text}
        placeholder="Type here to translate!"
        onBlur={(evt) => console.log('onBlur event:', evt.nativeEvent.text)}
        onChange={(evt) => console.log('onChange event:', evt.nativeEvent.text)}
        onChangeText={(text) => this.setState({ text })}
        onSubmitEditing={(evt) => console.log('onSubmitEditing event:', evt.nativeEvent.text)}
        onEndEditing={(evt) => console.log('onEndEditing event:', evt.nativeEvent.text)} />
      <Text style={styles.previewText}>
        {this.state.text}
      </Text>
      <TextInput style={styles.inputField} placeholder="Another to focus, meaningless" />
    </View>
  );
}

可以看出 onBluronEndEditing 對應(yīng)的兩個回調(diào)并沒有輸出我們預(yù)期的結(jié)果,而 RN 內(nèi)部似乎在這一步用 evt.nativeEvent.text 來設(shè)定了 <TextInput> 的顯示值(也許是 value 的值,我沒有仔細(xì)探究)。

解決辦法

知道了是 onBluronEndEditing 出的問題后,基本可以確定在這一部分加一些 patch 來處理。目前來看在我遇到的情況中 onBluronEndEditing 是被一起觸發(fā)的,所以在其中之一進(jìn)行修復(fù)即可。問題可能是 onEndEditing 觸發(fā)后,我們的 <TextInput> 并未如預(yù)期一樣更新顯示的值(即 props 里的 value ) ,我們希望利用 state 的變化來強(qiáng)制 <TextInput> 重新渲染。

onEndEditing={(evt) => this.setState({ text: evt.nativeEvent.text })} 這一行的引入可以解決這個問題(同時還更改了 onChange 的回調(diào),稍后說明)。

render () {
  return (
    <View style={styles.container}>
      <TextInput
        style={styles.inputField}
        value={this.state.text}
        placeholder="Type here to translate!"
        onChange={(evt) => this.setState({ text: evt.nativeEvent.text })}
        onChangeText={(text) => setTimeout(() => {this.setState({ text: text })})}
        onEndEditing={(evt) => this.setState({ text: evt.nativeEvent.text })} />
      <Text style={styles.previewText}>
        {this.state.text}
      </Text>
      <TextInput style={styles.inputField} placeholder="Another to focus, meaningless" />
    </View>
  );
}
repro3
repro3

如果你希望讓你的應(yīng)用看起來不允許中文輸入法,可以將 onChange={(evt) => this.setState({ text: evt.nativeEvent.text })} 這一行刪掉。視覺效果如下:

repro4
repro4

可以看出,這也許不是一個好主意,just FYI

獲取授權(quán)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容