我有 TextInput 组件,每当用户键入时它都会更改状态,但我意识到由于 TextInput 的值使用 this.state.text 作为值,双击空格不会在 iO 上产生句点。
是否有解决办法,以便双击空格仍然可以在 ios 上产生句号?
onChange =(text) => {
this.setState({text});
}
<TextInput
onChangeText={this.onChange}
onSubmitEditing={this.onSubmit}
value={this.state.text}
autoCapitalize="sentences"
blurOnSubmit={false}
editable={true}
/>
import React, { Component } from 'react';
import { AppRegistry, TouchableOpacity, View, TextInput } from 'react-native';
class UselessTextInput extends Component {
constructor(props) {
super(props)
this.state = {
lastPress: 0
}
}
onPress = () => {
var delta = new Date().getTime() - this.state.lastPress;
if (delta < 200) {
alert("DOUBLE TAP")
// double tap happend
}
this.setState({
lastPress: new Date().getTime()
})
}
render() {
return (
<TouchableOpacity onPress={this.onPress}>
<TextInput
pointerEvents="none"
/>
</TouchableOpacity>
);
}
}
export default class UselessTextInputMultiline extends Component {
constructor(props) {
super(props);
this.state = {
text: 'Useless Multiline Placeholder',
};
}
// If you type something in the text box that is a color, the background will change to that
// color.
render() {
return (
<View style={{
backgroundColor: this.state.text,
borderBottomColor: '#000000',
borderBottomWidth: 1
}}
>
<UselessTextInput
multiline={true}
numberOfLines={4}
onChangeText={(text) => this.setState({ text })}
value={this.state.text}
/>
</View>
);
}
}
// skip these lines if using Create React Native App
AppRegistry.registerComponent(
'AwesomeProject',
() => UselessTextInputMultiline
);
您可以根据您的要求进行编辑,我已经在 React Native 文档网站上尝试过了,并且成功了。
因此,我没有将值存储在状态中,而是在提交编辑时捕获它,捕获最终值。
<TextInput
onSubmitEditing={this.onSubmit}
value={this.state.text}
placeholder="Say Something.."
blurOnSubmit={false}
editable={true}
/>
然后我们创建一个提交函数,对文本执行某些操作并清除字段。
onSubmit = (e) => {
const text = e.nativeEvent.text;
this.setState({text}, () => { // <- Important Callback after setstate
//Whatever U want to do with the data here.
this.setState({text: ''}) // clear the field (this must be in the callback)
})
}
我们将 this.state.text 设置为 text,这样我们就可以在之后将其设置回 '' 打回来。如果不执行此步骤,状态不会改变,并且 组件不会刷新空字段。
我意识到通过这种方法,所有键盘功能都将正常工作,包括句点(.)的双倍空格,甚至复制和粘贴值,而无需使用setState。
更新:启用多行的解决方案。
以上适用于单行,对于多行,我们不使用 onSubmitEditing 而是使用按钮,我们需要向文本输入添加引用。
<TextInput
ref={input => { this.textMessage = input }} //Important.
//onSubmitEditing={this.onSubmit} //Remove so we can use newline
value={this.state.text}
placeholder="Say Something.."
blurOnSubmit={false}
editable={true}
multiline={true}
/>
创建一个执行提交的按钮
<Button onPress={this.onSubmit}
title="Send"
/>
有一种不同的方法可以通过 onSubmit 函数的引用来获取值
onSubmit = () => {
const text = this.textMessage._lastNativeText.trim(); //Remember the ref from textInput?
this.setState({text}, () => {
//Do whatever u want with the text here
this.setState({text: ''}) //clear the field
this.textMessage._lastNativeText = ''; //you need to clear this too
})
注意:如果不将 this.textMessage._lastNativeText 设置为空,则 当您单击“发送”时,将继续提交以前的值 按钮,即使 textInput 在视觉上看起来是空的。
import {useRef} from "react";
const useTextInputReplacer = () => {
const lastText = useRef<string>("");
const lastSpaceEnteredAt = useRef<number>();
const periodReplaceDisabled = useRef<boolean>(true);
const isLastCharacterAlphaNumeric = str => str[str.length - 1].match(/[a-zA-Z0-9]/);
return (_text) => {
if (lastText.current && _text.length) {
if (lastText.current.length < _text.length) { // add case
if (_text[_text.length - 1] === " " && !periodReplaceDisabled.current) {
const now = new Date().getTime();
if (lastSpaceEnteredAt.current && (now - lastSpaceEnteredAt.current) < 300) {
lastSpaceEnteredAt.current = undefined;
_text = _text.replace(/\s{2}$/, ". ");
periodReplaceDisabled.current = true;
} else if (!periodReplaceDisabled.current && isLastCharacterAlphaNumeric(lastText.current)) {
lastSpaceEnteredAt.current = now;
}
} else {
periodReplaceDisabled.current = !isLastCharacterAlphaNumeric(lastText.current);
}
} else if (lastText.current.length > _text.length) { // deletion case
periodReplaceDisabled.current = lastText.current[lastText.current.length - 1] === "." || !isLastCharacterAlphaNumeric(_text);
}
}
lastText.current = _text;
return _text;
};
};
然后在你的组件中
const textInputReplacer = useTextInputReplacer();
<Input
onChangeText={text => updateText(textInputReplacer(text))}
/>
为什么?因为一旦我们使用了 value,它就变成了一个受控的 TextInput,这意味着每次击键都会触发 onChangeText,并且它会由 React 控制。这可能会破坏本机行为。
只有 onChangeText 和更新状态是不受控制的方式,这是由本机平台控制的,因此允许您双击一段时间 - 也可以提高性能,因为并非所有内容都会在每次击键时重新渲染。除非您确实需要,否则不要使用价值。