怎么让TextInput获取或者失去焦点?focus()和blur()现在不支持吗?
-
@晴明
在一个子组件中
-
@晴明
在这里
-
@晴明 我是把这个方法传递给子组件调用 这样this的指向会有问题吗
-
贴完整代码吧,看不清楚
用三个`把代码括起来
-
@晴明 嗯 好的
父组件:/* eslint no-use-before-define: ["error", { "variables": false }] */ import PropTypes from 'prop-types'; import React from 'react'; import { StyleSheet, View, Text, Keyboard, ViewPropTypes, TouchableOpacity, Animated, TextInput, Platform, PixelRatio } from 'react-native'; // import Composer from './Composer'; import { MIN_COMPOSER_HEIGHT, DEFAULT_PLACEHOLDER } from './Constant'; import Send from './Send'; import Actions from './Actions'; import Color from './Color'; import Icon from 'react-native-vector-icons/MaterialIcons'; const MODE_TEXT = "mode_text"; const MODE_RECORD = "mode_record"; export default class InputToolbar extends React.Component { constructor(props) { super(props); this.keyboardWillShow = this.keyboardWillShow.bind(this); this.keyboardWillHide = this.keyboardWillHide.bind(this); this.state = { position: 'absolute', mode: MODE_TEXT, focused: false, isEmoji: false, actionVisible: false, actionAnim: new Animated.Value(0), // selection: {start: 0, end: 0}, }; } componentWillMount() { this.keyboardWillShowListener = Keyboard.addListener('keyboardWillShow', this.keyboardWillShow); this.keyboardWillHideListener = Keyboard.addListener('keyboardWillHide', this.keyboardWillHide); } componentWillUnmount() { this.keyboardWillShowListener.remove(); this.keyboardWillHideListener.remove(); } keyboardWillShow() { if (this.state !== 'relative') { this.setState({ position: 'relative', }); } } keyboardWillHide() { if (this.state !== 'absolute') { this.setState({ position: 'absolute', }); } } renderActions() { if (this.props.renderActions) { return this.props.renderActions(this.props); } else if (this.props.onPressActionButton) { return <Actions {...this.props} />; } return null; } onActionsPress = () => { let actionVisible = this.state.actionVisible; if (actionVisible) { console.warn(this.search) if (this.search) { console.warn(111111) this.search.focus(); } /*Animated.timing( this.state.actionAnim, {toValue: 0,useNativeDriver: true,} ).start();*/ // return; } if (this.search) { this.search.blur(); } actionVisible = !actionVisible; this.setState({actionVisible: actionVisible, isEmoji: false}); if (actionVisible) { // this.actionBarHeight = ACTION_BUTTON_HEIGHT; // this.onHeightChange(); } // Animated.timing( // this.state.actionAnim, // {toValue: 1,useNativeDriver: true,} // ).start(); } _renderActions = () => { if (this.props.renderAccessory) { return this.props.renderAccessory(this.props) } return ( <View style={{backgroundColor:'red',height:220}}> <Text>自定义</Text> </View> ) } renderSend() { if (this.props.renderSend) { return this.props.renderSend(this.props); } return <Send onActionsPress={this.onActionsPress} {...this.props} />; } onContentSizeChange(e) { const { contentSize } = e.nativeEvent; // Support earlier versions of React Native on Android. if (!contentSize) return; if ( !this.contentSize || this.contentSize.width !== contentSize.width || this.contentSize.height !== contentSize.height ) { this.contentSize = contentSize; this.props.onInputSizeChanged(this.contentSize); } } onChangeText(text) { this.props.onTextChanged(text); } renderComposer() { if (this.props.renderComposer) { return this.props.renderComposer(this.props); } return ( <TextInput ref = {search => this.search = search} // testID={this.props.placeholder} // accessible onFocus={this.onFocus} editable={true} maxLength={500} onBlur={this.handleBlurSearch.bind(this)} keyboardType='default' returnKeyType={'send'} autoCapitalize='none' accessibilityLabel={this.props.placeholder} placeholder={this.props.placeholder} placeholderTextColor={this.props.placeholderTextColor} multiline={this.props.multiline} onChange={(e) => this.onContentSizeChange(e)} onContentSizeChange={(e) => this.onContentSizeChange(e)} onChangeText={(text) => this.onChangeText(text)} style={[styles.textInput, this.props.textInputStyle, { height: this.props.composerHeight }]} autoFocus={this.state.focused} value={this.props.text} enablesReturnKeyAutomatically underlineColorAndroid="transparent" keyboardAppearance={this.props.keyboardAppearance} {...this.props.textInputProps} enablesReturnKeyAutomatically={true} // onSelectionChange={({nativeEvent: {selection}}) => this.setState({selection})} /> ) } onFocus = () => { this.setState({ isEmoji: false, actionVisible: false, }) } handleBlurSearch() { this.setState({focused: false}); } renderAccessory() { if (this.props.renderAccessory) { return ( <View style={[styles.accessory, this.props.accessoryStyle]}>{this.props.renderAccessory(this.props)}</View> ); } return null; } renderRecordInput() { // return <Audio onSend={this.props.onSend}/> } handleRecordMode() { const {isEmoji, actionVisible} = this.state; if (this.state.mode === MODE_RECORD) { return; } this.setState({ // isEmoji: false, // actionVisible: false, focused: false, mode: MODE_RECORD }); // if (isEmoji || actionVisible) { // this.actionBarHeight = 0; // this.onHeightChange(); // } // NimUtils.onTouchVoice(); } handleTextMode() { if (this.state.mode === MODE_TEXT) { return; } this.setState({mode: MODE_TEXT, focused: true,}); } _renderEmojiButton = () => { const {isEmoji} = this.state; return ( <TouchableOpacity style={{ paddingLeft: 5, paddingRight: 5, alignSelf: "stretch", justifyContent: "center" }} onPress={this.handleEmojiOpen.bind(this)}> { isEmoji ? <Icon name={'keyboard'} size={30} color={'#666'}/> : <Icon name="insert-emoticon" size={30} color={'#666'}/> } </TouchableOpacity> ) } handleEmojiOpen() { let isEmoji = this.state.isEmoji; isEmoji = !isEmoji; this.setState({ isEmoji: isEmoji, // actionVisible: false, mode: MODE_TEXT }); } render() { const { mode, actionVisible } = this.state; return ( <View style={[styles.container, this.props.containerStyle, { position: this.state.position }]}> <View style={[styles.primary, this.props.primaryStyle]}> {mode === MODE_TEXT ? <TouchableOpacity style={{alignSelf: "stretch", justifyContent: "center", paddingLeft: 8}} onPress={this.handleRecordMode.bind(this)}> <Icon name={'keyboard-voice'} size={30} color={'#666'}/> </TouchableOpacity> : <TouchableOpacity style={{alignSelf: "stretch", justifyContent: "center", paddingLeft: 8}} onPress={this.handleTextMode.bind(this)}> <Icon name={'keyboard'} size={30} color={'#666'}/> </TouchableOpacity>} {mode === MODE_TEXT ? this.renderComposer() : this.renderRecordInput()} {this._renderEmojiButton()} {this.renderSend()} </View> { actionVisible && this._renderActions() } </View> ); } } const styles = StyleSheet.create({ container: { borderTopWidth: StyleSheet.hairlineWidth, borderTopColor: Color.defaultColor, backgroundColor: '#F4F4F6', bottom: 0, left: 0, right: 0, }, primary: { flexDirection: 'row', alignItems: 'flex-end', }, accessory: { height: 44, }, textInput: { flex: 1, marginLeft: 5, marginRight: 5, fontSize: 16, lineHeight: 16, height: 35, marginTop: Platform.select({ ios: 6, android: 0, }), marginBottom: Platform.select({ ios: 5, android: 3, }), borderColor: '#DDDDDD', borderWidth: 1/PixelRatio.get(), marginTop: 5, borderRadius: 4, backgroundColor: '#fff' }, }); InputToolbar.defaultProps = { renderAccessory: null, renderActions: null, renderSend: null, renderComposer: null, containerStyle: {}, primaryStyle: {}, accessoryStyle: {}, onPressActionButton: () => {}, }; InputToolbar.propTypes = { renderAccessory: PropTypes.func, renderActions: PropTypes.func, renderSend: PropTypes.func, renderComposer: PropTypes.func, onPressActionButton: PropTypes.func, containerStyle: ViewPropTypes.style, primaryStyle: ViewPropTypes.style, accessoryStyle: ViewPropTypes.style, };
子组件:
/* eslint no-use-before-define: ["error", { "variables": false }] */ import PropTypes from 'prop-types'; import React from 'react'; import { StyleSheet, Text, TouchableOpacity, View, ViewPropTypes } from 'react-native'; import Color from './Color'; import Icon from 'react-native-vector-icons/MaterialIcons'; export default function Send({ text, containerStyle, onSend, children, textStyle, label, alwaysShowSend, onActionsPress }) { if (alwaysShowSend || text.trim().length > 0) { return ( <TouchableOpacity testID="send" accessible accessibilityLabel="send" style={[styles.container, containerStyle]} onPress={() => { onSend({ text: text.trim() }, true); }} accessibilityTraits="button" > <View>{children || <Text style={[styles.text, textStyle]}>{label}</Text>}</View> </TouchableOpacity> ); } return ( <TouchableOpacity style={{alignSelf: "stretch", justifyContent: "center", paddingRight: 8}} onPress={onActionsPress}> <Icon name="add-circle-outline" size={30} color={'#666'}/> </TouchableOpacity> ) } const styles = StyleSheet.create({ container: { height: 44, justifyContent: 'flex-end', }, text: { color: Color.defaultBlue, fontWeight: '600', fontSize: 17, backgroundColor: Color.backgroundTransparent, marginBottom: 12, marginLeft: 10, marginRight: 10, }, }); Send.defaultProps = { text: '', onSend: () => {}, label: '发送', containerStyle: {}, textStyle: {}, children: null, alwaysShowSend: false, }; Send.propTypes = { text: PropTypes.string, onSend: PropTypes.func, label: PropTypes.string, containerStyle: ViewPropTypes.style, textStyle: Text.propTypes.style, children: PropTypes.element, alwaysShowSend: PropTypes.bool, };
-
单看代码没发现问题,如果那些if else的流程符合预期的话
打印结果呢?
-
@晴明 我打印this.search就是undefined的 我找不到原因
-
@晴明 我是想通过focus()和blur()来实现输入框是否获取焦点 但是我在这里就是获取不到ref
在我项目的其他地方我是可以通过this.refs获取到的 但是这里不行
对了 出问题的代码是依赖包里面的文件 我在改react-native-gifted-chat这个包的源代码 出现这个问题是因为我没有把它放在项目目录下吗?
-
undefined那就是ref没有执行咯,所以我说你那些if else的流程确定正确吗?这些基本逻辑都应该断点调试啊,方法是否按期望的顺序执行甚至是否有执行,是否按期望的输入值输入,期望的返回值返回等等,所有的调试都是这样啊。你文件放在哪无所谓啊(规不规范另说),反正最终都是揉到一起在内存里执行
-
@晴明 这些if else是正确的 因为我的视图是正确渲染了 所有其他逻辑都没有问题 就是这里的ref获取不到
-
@晴明 textInput所在的组件的父组件的代码是这样的:
/* eslint no-param-reassign: 0, no-use-before-define: ["error", { "variables": false }], no-return-assign: 0, no-mixed-operators: 0, react/sort-comp: 0 */ import PropTypes from 'prop-types'; import React from 'react'; import { Animated, Platform, StyleSheet, View } from 'react-native'; import ActionSheet from '@expo/react-native-action-sheet'; import moment from 'moment'; import uuid from 'uuid'; import * as utils from './utils'; import Actions from './Actions'; import Avatar from './Avatar'; import Bubble from './Bubble'; import SystemMessage from './SystemMessage'; import MessageImage from './MessageImage'; import MessageText from './MessageText'; import Composer from './Composer'; import Day from './Day'; import InputToolbar from './InputToolbar'; import LoadEarlier from './LoadEarlier'; import Message from './Message'; import MessageContainer from './MessageContainer'; import Send from './Send'; import Time from './Time'; import GiftedAvatar from './GiftedAvatar'; import { MIN_COMPOSER_HEIGHT, MAX_COMPOSER_HEIGHT, DEFAULT_PLACEHOLDER, TIME_FORMAT, DATE_FORMAT, } from './Constant'; global.inputRef = null; moment.locale('zh-cn', { months: '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'), monthsShort: '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'), weekdays: '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'), weekdaysShort: '周日_周一_周二_周三_周四_周五_周六'.split('_'), weekdaysMin: '日_一_二_三_四_五_六'.split('_'), longDateFormat: { LT: 'Ah点mm分', LTS: 'Ah点m分s秒', L: 'YYYY-MM-DD', LL: 'YYYY年MMMD日', LLL: 'YYYY年MMMD日Ah点mm分', LLLL: 'YYYY年MMMD日ddddAh点mm分', l: 'YYYY-MM-DD', ll: 'YYYY年MMMD日', lll: 'YYYY年MMMD日Ah点mm分', llll: 'YYYY年MMMD日ddddAh点mm分' }, meridiemParse: /凌晨|早上|上午|中午|下午|晚上/, meridiemHour: function (h, meridiem) { let hour = h; if (hour === 12) { hour = 0; } if (meridiem === '凌晨' || meridiem === '早上' || meridiem === '上午') { return hour; } else if (meridiem === '下午' || meridiem === '晚上') { return hour + 12; } else { // '中午' return hour >= 11 ? hour : hour + 12; } }, meridiem: function (hour, minute, isLower) { const hm = hour * 100 + minute; if (hm < 600) { return '凌晨'; } else if (hm < 900) { return '早上'; } else if (hm < 1130) { return '上午'; } else if (hm < 1230) { return '中午'; } else if (hm < 1800) { return '下午'; } else { return '晚上'; } }, calendar: { sameDay: function () { return this.minutes() === 0 ? '[今天]Ah[点整]' : '[今天]LT'; }, nextDay: function () { return this.minutes() === 0 ? '[明天]Ah[点整]' : '[明天]LT'; }, lastDay: function () { return this.minutes() === 0 ? '[昨天]Ah[点整]' : '[昨天]LT'; }, nextWeek: function () { let startOfWeek, prefix; startOfWeek = moment().startOf('week'); prefix = this.diff(startOfWeek, 'days') >= 7 ? '[下]' : '[本]'; return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm'; }, lastWeek: function () { let startOfWeek, prefix; startOfWeek = moment().startOf('week'); prefix = this.unix() < startOfWeek.unix() ? '[上]' : '[本]'; return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm'; }, sameElse: 'LL' }, ordinalParse: /\d{1,2}(日|月|周)/, ordinal: function (number, period) { switch (period) { case 'd': case 'D': case 'DDD': return number + '日'; case 'M': return number + '月'; case 'w': case 'W': return number + '周'; default: return number; } }, relativeTime: { future: '%s内', past: '%s前', s: '几秒', m: '1 分钟', mm: '%d 分钟', h: '1 小时', hh: '%d 小时', d: '1 天', dd: '%d 天', M: '1 个月', MM: '%d 个月', y: '1 年', yy: '%d 年' }, week: { // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效 dow: 1, // Monday is the first day of the week. doy: 4 // The week that contains Jan 4th is the first week of the year. } }); class GiftedChat extends React.Component { constructor(props) { super(props); // default values this._isMounted = false; this._keyboardHeight = 0; this._bottomOffset = 0; this._maxHeight = null; this._isFirstLayout = true; this._locale = 'en'; this._messages = []; this.state = { isInitialized: false, // initialization will calculate maxHeight before rendering the chat composerHeight: MIN_COMPOSER_HEIGHT, messagesContainerHeight: null, typingDisabled: false, }; this.onKeyboardWillShow = this.onKeyboardWillShow.bind(this); this.onKeyboardWillHide = this.onKeyboardWillHide.bind(this); this.onKeyboardDidShow = this.onKeyboardDidShow.bind(this); this.onKeyboardDidHide = this.onKeyboardDidHide.bind(this); this.onSend = this.onSend.bind(this); this.getLocale = this.getLocale.bind(this); this.onInputSizeChanged = this.onInputSizeChanged.bind(this); this.onInputTextChanged = this.onInputTextChanged.bind(this); this.onMainViewLayout = this.onMainViewLayout.bind(this); this.onInitialLayoutViewLayout = this.onInitialLayoutViewLayout.bind(this); this.invertibleScrollViewProps = { inverted: this.props.inverted, keyboardShouldPersistTaps: this.props.keyboardShouldPersistTaps, onKeyboardWillShow: this.onKeyboardWillShow, onKeyboardWillHide: this.onKeyboardWillHide, onKeyboardDidShow: this.onKeyboardDidShow, onKeyboardDidHide: this.onKeyboardDidHide, }; } static append(currentMessages = [], messages, inverted = true) { if (!Array.isArray(messages)) { messages = [messages]; } return inverted ? messages.concat(currentMessages) : currentMessages.concat(messages); } static prepend(currentMessages = [], messages, inverted = true) { if (!Array.isArray(messages)) { messages = [messages]; } return inverted ? currentMessages.concat(messages) : messages.concat(currentMessages); } getChildContext() { return { actionSheet: () => this._actionSheetRef, getLocale: this.getLocale, }; } componentWillMount() { const { messages, text } = this.props; this.setIsMounted(true); this.initLocale(); this.setMessages(messages || []); this.setTextFromProp(text); } componentWillUnmount() { this.setIsMounted(false); } componentWillReceiveProps(nextProps = {}) { const { messages, text } = nextProps; this.setMessages(messages || []); this.setTextFromProp(text); } initLocale() { if (this.props.locale === null || moment.locales().indexOf(this.props.locale) === -1) { this.setLocale('en'); } else { this.setLocale(this.props.locale); } } setLocale(locale) { this._locale = locale; } getLocale() { return this._locale; } setTextFromProp(textProp) { // Text prop takes precedence over state. if (textProp !== undefined && textProp !== this.state.text) { this.setState({ text: textProp }); } } getTextFromProp(fallback) { if (this.props.text === undefined) { return fallback; } return this.props.text; } setMessages(messages) { this._messages = messages; } getMessages() { return this._messages; } setMaxHeight(height) { this._maxHeight = height; } getMaxHeight() { return this._maxHeight; } setKeyboardHeight(height) { this._keyboardHeight = height; } getKeyboardHeight() { if (Platform.OS === 'android' && !this.props.forceGetKeyboardHeight) { // For android: on-screen keyboard resized main container and has own height. // @see https://developer.android.com/training/keyboard-input/visibility.html // So for calculate the messages container height ignore keyboard height. return 0; } return this._keyboardHeight; } setBottomOffset(value) { this._bottomOffset = value; } getBottomOffset() { return this._bottomOffset; } setIsFirstLayout(value) { this._isFirstLayout = value; } getIsFirstLayout() { return this._isFirstLayout; } setIsTypingDisabled(value) { this.setState({ typingDisabled: value, }); } getIsTypingDisabled() { return this.state.typingDisabled; } setIsMounted(value) { this._isMounted = value; } getIsMounted() { return this._isMounted; } // TODO: setMinInputToolbarHeight getMinInputToolbarHeight() { return this.props.renderAccessory ? this.props.minInputToolbarHeight * 2 : this.props.minInputToolbarHeight; } calculateInputToolbarHeight(composerHeight) { return composerHeight + (this.getMinInputToolbarHeight() - MIN_COMPOSER_HEIGHT); } /** * Returns the height, based on current window size, without taking the keyboard into account. */ getBasicMessagesContainerHeight(composerHeight = this.state.composerHeight) { return this.getMaxHeight() - this.calculateInputToolbarHeight(composerHeight); } /** * Returns the height, based on current window size, taking the keyboard into account. */ getMessagesContainerHeightWithKeyboard(composerHeight = this.state.composerHeight) { return this.getBasicMessagesContainerHeight(composerHeight) - this.getKeyboardHeight() + this.getBottomOffset(); } prepareMessagesContainerHeight(value) { if (this.props.isAnimated === true) { return new Animated.Value(value); } return value; } onKeyboardWillShow(e) { this.setIsTypingDisabled(true); this.setKeyboardHeight(e.endCoordinates ? e.endCoordinates.height : e.end.height); this.setBottomOffset(this.props.bottomOffset); const newMessagesContainerHeight = this.getMessagesContainerHeightWithKeyboard(); if (this.props.isAnimated === true) { Animated.timing(this.state.messagesContainerHeight, { toValue: newMessagesContainerHeight, duration: 210, }).start(); } else { this.setState({ messagesContainerHeight: newMessagesContainerHeight, }); } } onKeyboardWillHide() { this.setIsTypingDisabled(true); this.setKeyboardHeight(0); this.setBottomOffset(0); const newMessagesContainerHeight = this.getBasicMessagesContainerHeight(); if (this.props.isAnimated === true) { Animated.timing(this.state.messagesContainerHeight, { toValue: newMessagesContainerHeight, duration: 210, }).start(); } else { this.setState({ messagesContainerHeight: newMessagesContainerHeight, }); } } onKeyboardDidShow(e) { if (Platform.OS === 'android') { this.onKeyboardWillShow(e); } this.setIsTypingDisabled(false); } onKeyboardDidHide(e) { if (Platform.OS === 'android') { this.onKeyboardWillHide(e); } this.setIsTypingDisabled(false); } scrollToBottom(animated = true) { if (this._messageContainerRef === null) { return; } this._messageContainerRef.scrollTo({ y: 0, animated }); } renderMessages() { const AnimatedView = this.props.isAnimated === true ? Animated.View : View; return ( <AnimatedView style={{ height: this.state.messagesContainerHeight, }} > <MessageContainer {...this.props} invertibleScrollViewProps={this.invertibleScrollViewProps} messages={this.getMessages()} ref={(component) => (this._messageContainerRef = component)} /> {this.renderChatFooter()} </AnimatedView> ); } onSend(messages = [], shouldResetInputToolbar = false) { if (!Array.isArray(messages)) { messages = [messages]; } messages = messages.map((message) => { return { ...message, user: this.props.user, createdAt: new Date(), _id: this.props.messageIdGenerator(), }; }); if (shouldResetInputToolbar === true) { this.setIsTypingDisabled(true); this.resetInputToolbar(); } this.props.onSend(messages); this.scrollToBottom(); if (shouldResetInputToolbar === true) { setTimeout(() => { if (this.getIsMounted() === true) { this.setIsTypingDisabled(false); } }, 100); } } resetInputToolbar() { if (this.textInput) { this.textInput.clear(); } this.notifyInputTextReset(); const newComposerHeight = MIN_COMPOSER_HEIGHT; const newMessagesContainerHeight = this.getMessagesContainerHeightWithKeyboard(newComposerHeight); this.setState({ text: this.getTextFromProp(''), composerHeight: newComposerHeight, messagesContainerHeight: this.prepareMessagesContainerHeight(newMessagesContainerHeight), }); } focusTextInput() { if (this.textInput) { this.textInput.focus(); } } onInputSizeChanged(size) { const newComposerHeight = Math.max(MIN_COMPOSER_HEIGHT, Math.min(MAX_COMPOSER_HEIGHT, size.height)); const newMessagesContainerHeight = this.getMessagesContainerHeightWithKeyboard(newComposerHeight); this.setState({ composerHeight: newComposerHeight, messagesContainerHeight: this.prepareMessagesContainerHeight(newMessagesContainerHeight), }); } onInputTextChanged(text) { if (this.getIsTypingDisabled()) { return; } if (this.props.onInputTextChanged) { this.props.onInputTextChanged(text); } // Only set state if it's not being overridden by a prop. if (this.props.text === undefined) { this.setState({ text }); } } notifyInputTextReset() { if (this.props.onInputTextChanged) { this.props.onInputTextChanged(''); } } onInitialLayoutViewLayout(e) { const { layout } = e.nativeEvent; if (layout.height <= 0) { return; } this.notifyInputTextReset(); this.setMaxHeight(layout.height); const newComposerHeight = MIN_COMPOSER_HEIGHT; const newMessagesContainerHeight = this.getMessagesContainerHeightWithKeyboard(newComposerHeight); this.setState({ isInitialized: true, text: this.getTextFromProp(''), composerHeight: newComposerHeight, messagesContainerHeight: this.prepareMessagesContainerHeight(newMessagesContainerHeight), }); } onMainViewLayout(e) { // fix an issue when keyboard is dismissing during the initialization const { layout } = e.nativeEvent; if (this.getMaxHeight() !== layout.height || this.getIsFirstLayout() === true) { this.setMaxHeight(layout.height); this.setState({ messagesContainerHeight: this.prepareMessagesContainerHeight(this.getBasicMessagesContainerHeight()), }); } if (this.getIsFirstLayout() === true) { this.setIsFirstLayout(false); } } renderInputToolbar() { const inputToolbarProps = { ...this.props, text: this.getTextFromProp(this.state.text), composerHeight: Math.max(MIN_COMPOSER_HEIGHT, this.state.composerHeight), onSend: this.onSend, onInputSizeChanged: this.onInputSizeChanged, onTextChanged: this.onInputTextChanged, textInputProps: { ...this.props.textInputProps, ref: (textInput) => (this.textInput = textInput), maxLength: this.getIsTypingDisabled() ? 0 : this.props.maxInputLength, }, }; if (this.props.renderInputToolbar) { return this.props.renderInputToolbar(inputToolbarProps); } return ( <InputToolbar {...inputToolbarProps} /> ); } renderChatFooter() { if (this.props.renderChatFooter) { const footerProps = { ...this.props, }; return this.props.renderChatFooter(footerProps); } return null; } renderLoading() { if (this.props.renderLoading) { return this.props.renderLoading(); } return null; } render() { if (this.state.isInitialized === true) { return ( <ActionSheet ref={(component) => (this._actionSheetRef = component)}> <View style={styles.container} onLayout={this.onMainViewLayout}> {this.renderMessages()} {this.renderInputToolbar()} </View> </ActionSheet> ); } return ( <View style={styles.container} onLayout={this.onInitialLayoutViewLayout}> {this.renderLoading()} </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, }, }); GiftedChat.childContextTypes = { actionSheet: PropTypes.func, getLocale: PropTypes.func, }; GiftedChat.defaultProps = { messages: [], text: undefined, placeholder: DEFAULT_PLACEHOLDER, messageIdGenerator: () => uuid.v4(), user: {}, onSend: () => { }, locale: null, timeFormat: TIME_FORMAT, dateFormat: DATE_FORMAT, isAnimated: Platform.select({ ios: true, android: false, }), loadEarlier: false, onLoadEarlier: () => { }, isLoadingEarlier: false, renderLoading: null, renderLoadEarlier: null, renderAvatar: undefined, showUserAvatar: false, onPressAvatar: null, renderAvatarOnTop: false, renderBubble: null, renderSystemMessage: null, onLongPress: null, renderMessage: null, renderMessageText: null, renderMessageImage: null, imageProps: {}, lightboxProps: {}, textInputProps: {}, listViewProps: {}, renderCustomView: null, renderDay: null, renderTime: null, renderFooter: null, renderChatFooter: null, renderInputToolbar: null, renderComposer: null, renderActions: null, renderSend: null, renderAccessory: null, onPressActionButton: null, bottomOffset: 0, minInputToolbarHeight: 44, keyboardShouldPersistTaps: Platform.select({ ios: 'never', android: 'always', }), onInputTextChanged: null, maxInputLength: null, forceGetKeyboardHeight: false, inverted: true, }; GiftedChat.propTypes = { messages: PropTypes.arrayOf(PropTypes.object), text: PropTypes.string, placeholder: PropTypes.string, messageIdGenerator: PropTypes.func, user: PropTypes.object, onSend: PropTypes.func, locale: PropTypes.string, timeFormat: PropTypes.string, dateFormat: PropTypes.string, isAnimated: PropTypes.bool, loadEarlier: PropTypes.bool, onLoadEarlier: PropTypes.func, isLoadingEarlier: PropTypes.bool, renderLoading: PropTypes.func, renderLoadEarlier: PropTypes.func, renderAvatar: PropTypes.func, showUserAvatar: PropTypes.bool, onPressAvatar: PropTypes.func, renderAvatarOnTop: PropTypes.bool, renderBubble: PropTypes.func, renderSystemMessage: PropTypes.func, onLongPress: PropTypes.func, renderMessage: PropTypes.func, renderMessageText: PropTypes.func, renderMessageImage: PropTypes.func, imageProps: PropTypes.object, lightboxProps: PropTypes.object, renderCustomView: PropTypes.func, renderDay: PropTypes.func, renderTime: PropTypes.func, renderFooter: PropTypes.func, renderChatFooter: PropTypes.func, renderInputToolbar: PropTypes.func, renderComposer: PropTypes.func, renderActions: PropTypes.func, renderSend: PropTypes.func, renderAccessory: PropTypes.func, onPressActionButton: PropTypes.func, bottomOffset: PropTypes.number, minInputToolbarHeight: PropTypes.number, listViewProps: PropTypes.object, keyboardShouldPersistTaps: PropTypes.oneOf(['always', 'never', 'handled']), onInputTextChanged: PropTypes.func, maxInputLength: PropTypes.number, forceGetKeyboardHeight: PropTypes.bool, inverted: PropTypes.bool, textInputProps: PropTypes.object, }; export { GiftedChat, Actions, Avatar, Bubble, SystemMessage, MessageImage, MessageText, Composer, Day, InputToolbar, LoadEarlier, Message, MessageContainer, Send, Time, GiftedAvatar, utils, };
-
@1111mp 在render中ActionSheet有一个ref 这个会影响textInput的ref吗?
-
你看死的代码看不出其值的变化,
你要做的就是在ref中打上断点,在onpress里打上断点,在各个可疑的地方打上断点,然后观察this的值,this.search的值,直到发现在哪个地方不对,再反过来思考哪里的流程不对
-
@晴明 嗯 我刚刚在ref中加了调试 发现这个方法没有执行 现在在找没有执行ref的问题
-
@1111mp 其他地方的打印和调试代码都有执行
-
@晴明
这里的代码我有点看不懂 这里的ref应该是textInput的ref吧?是不是这里的问题导致?
-
@晴明 你好 我已经解决了这个问题 就是我最后贴出来的代码造成的 ref在父组件中已经传递并执行了 所以我不需要在子组件中使用ref 在textInput的父组件中是可以获取到的 真的非常感谢你 谢谢啊
-
不要轻易用{...this.props}这种笼统的写法(不可控,你根本不知道哪些属性重叠),你的问题就是{...this.props.textInputProps}里的ref覆盖了单独写的ref
-
@晴明 好的 谢谢 我会注意的