所以这是react-native的一个缺点。
听写失败的原因是当您听写时组件会自行重新渲染。每当它重新渲染时,Siri 面板都会最小化,因此听写会突然结束。
为了解决这个问题,我创建了一个 TextInput 包装组件,它依赖于shouldComponentUpdate
每当值发生变化时,阻止我的 TextInput 包装器重新渲染。
现在我们不是立即重新渲染,而是setState
仅在特定时间的去抖之后。 (500-1500 之间的任何值都可以)
尝试一下,让我知道它是否适合您。
import React from 'react';
import debounce from 'lodash.debounce';
import PropTypes from 'prop-types';
import { TextInput } from 'react-native';
const CHANGE_TEXT_DELAY_UNTIL_DISPATCH = 700;
// enforces dication safety so that siri can hear more than 1 words
class DictationSafeTextInput extends React.Component {
//
constructor(props) {
super(props);
this.onValueChangeDelayed =
debounce(this.onValueChangeDelayed.bind(this), CHANGE_TEXT_DELAY_UNTIL_DISPATCH);
this.state = {
value: props.value,
};
}
componentWillReceiveProps(nextProps) {
if (this.props.value !== nextProps.value) {
this.onValueChangeDelayed(nextProps.value);
}
}
shouldComponentUpdate(nextProps, nextState) {
const pastProps = this.props;
const shoudlUpdate = (
// pastProps.value !== nextProps.value
// ||
nextState.value !== this.state.value
||
pastProps.style !== nextProps.style
||
pastProps.editable !== nextProps.editable
||
pastProps.onContentSizeChange !== nextProps.onContentSizeChange
||
pastProps.onSubmitEditing !== nextProps.onSubmitEditing
||
pastProps.onChangeText !== nextProps.onChangeText
||
pastProps.onFocus !== nextProps.onFocus
||
pastProps.onBlur !== nextProps.onBlur
||
pastProps.innerTextInputRef !== nextProps.innerTextInputRef
||
pastProps.blurOnSubmit !== nextProps.blurOnSubmit
||
pastProps.autoFocus !== nextProps.autoFocus
||
pastProps.pointerEvents !== nextProps.pointerEvents
||
pastProps.maxLength !== nextProps.maxLength
||
pastProps.returnKeyType !== nextProps.returnKeyType
||
pastProps.placeholderTextColor !== nextProps.placeholderTextColor
||
pastProps.placeholder !== nextProps.placeholder
||
pastProps.underlineColorAndroid !== nextProps.underlineColorAndroid
||
pastProps.autoCorrect !== nextProps.autoCorrect
||
pastProps.multiline !== nextProps.multiline
||
pastProps.autoCapitalize !== nextProps.autoCapitalize
||
pastProps.keyboardType !== nextProps.keyboardType
||
pastProps.numberOfLines !== nextProps.numberOfLines
||
pastProps.defaultValue !== nextProps.defaultValue
||
pastProps.dictationSafety !== nextProps.dictationSafety
);
return shoudlUpdate;
}
componentWillUnmount() {
this.onValueChangeDelayed.cancel();
if (this.onSubmitEditingTimeout != null) {
clearTimeout(this.onSubmitEditingTimeout);
this.onSubmitEditingTimeout = null;
}
}
onValueChangeDelayed(newValue) {
if (newValue !== this.state.value) {
this.setState({
value: newValue,
});
}
}
render() {
const {
dictationSafety,
onChangeText,
onBlur,
innerTextInputRef,
onSubmitEditing,
} = this.props;
if (dictationSafety && onChangeText) {
return (
<TextInput
ref={(r) => {
if (innerTextInputRef != null) {
innerTextInputRef(r);
}
}}
{...this.props}
value={this.state.value}
onChangeText={(newValue) => {
if (this.props.onChangeText) {
this.props.onChangeText(newValue);
}
}}
onBlur={() => {
this.onValueChangeDelayed.flush();
if (onBlur) {
onBlur();
}
}}
onSubmitEditing={() => {
this.onValueChangeDelayed.flush();
if (onSubmitEditing) {
this.onSubmitEditingTimeout = setTimeout(() => {
onSubmitEditing();
}, CHANGE_TEXT_DELAY_UNTIL_DISPATCH);
}
}}
/>
);
}
return (
<TextInput
{...this.props}
/>
);
}
}
DictationSafeTextInput.defaultProps = {
dictationSafety: true,
};
DictationSafeTextInput.propTypes = {
innerTextInputRef: PropTypes.oneOfType([
PropTypes.func,
PropTypes.object,
]),
onChangeText: PropTypes.func,
onBlur: PropTypes.func,
onSubmitEditing: PropTypes.func,
dictationSafety: PropTypes.bool,
pointerEvents: PropTypes.oneOf([
'box-none',
'none',
'box-only',
'auto',
]),
autoCorrect: PropTypes.bool,
style: PropTypes.oneOfType([
PropTypes.object,
PropTypes.array,
PropTypes.number,
]),
onContentSizeChange: PropTypes.func,
editable: PropTypes.bool,
// eslint-disable-next-line
underlineColorAndroid: PropTypes.any,
value: PropTypes.string,
multiline: PropTypes.bool,
placeholder: PropTypes.string,
// eslint-disable-next-line
placeholderTextColor: PropTypes.any,
returnKeyType: PropTypes.oneOf([
// Cross-platform
'done',
'go',
'next',
'search',
'send',
// Android-only
'none',
'previous',
// iOS-only
'default',
'emergency-call',
'google',
'join',
'route',
'yahoo',
]),
autoFocus: PropTypes.bool,
blurOnSubmit: PropTypes.bool,
autoCapitalize: PropTypes.oneOf([
'none',
'sentences',
'words',
'characters',
]),
keyboardType: PropTypes.oneOf([
'default',
'email-address',
'numeric',
'phone-pad',
'number-pad',
'ascii-capable',
'numbers-and-punctuation',
'url',
'name-phone-pad',
'decimal-pad',
'twitter',
'web-search',
'visible-password',
]),
onFocus: PropTypes.func,
numberOfLines: PropTypes.number,
defaultValue: PropTypes.string,
maxLength: PropTypes.number,
};
export default DictationSafeTextInput;