怎么让TextInput获取或者失去焦点?focus()和blur()现在不支持吗?



  • 在哪打印的,截图贴出来,有用箭头函数绑定this吗





  • @晴明 在这个方法中打印的



  • 这方法又在哪调用的



  • @晴明 0_1539165954283_bda88574-73f5-478b-92a9-6740f3de3f5b-image.png
    在一个子组件中



  • @晴明 0_1539165985300_1d145878-caf6-4ad9-bed2-086fd4a96094-image.png
    在这里



  • @晴明 我是把这个方法传递给子组件调用 这样this的指向会有问题吗



  • 贴完整代码吧,看不清楚

    用三个`把代码括起来

    0_1539166130761_1f96b1d2-8e37-43cb-be4a-296688531982-image.png



  • @晴明 嗯 好的
    父组件:

    /* 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吗?
    0_1539167502838_7625f0a5-2da0-4aed-8c00-a632d1886745-image.png



  • 你看死的代码看不出其值的变化,
    你要做的就是在ref中打上断点,在onpress里打上断点,在各个可疑的地方打上断点,然后观察this的值,this.search的值,直到发现在哪个地方不对,再反过来思考哪里的流程不对



  • @晴明 嗯 我刚刚在ref中加了调试 发现这个方法没有执行 现在在找没有执行ref的问题



  • @1111mp 其他地方的打印和调试代码都有执行



  • @晴明 0_1539168707899_4a1bef37-ef54-4bc7-852b-de895bb237f7-image.png
    这里的代码我有点看不懂 这里的ref应该是textInput的ref吧?是不是这里的问题导致?