【问题标题】:React-Native Expo issue with TextInputTextInput 的 React-Native Expo 问题
【发布时间】:2017-08-10 04:00:48
【问题描述】:

我正在使用 React-Native、Redux、React-Navigation 和 Expo 创建一个简单的事件跟踪器应用程序,但我在一个相当琐碎的部分上遇到了一些麻烦。

我有一个表单屏幕,您可以在其中输入活动名称、日期和其他信息。我正在使用<TextInput/> 输入事件的名称,但它不会用于onChange 事件,只有onChangeText。此外,当我使用onChange 事件时,导航上的 Back 按钮变得无响应,并且无论我点击哪里,光标都只保留在 TextInput 中

我遇到了另一个与内存有关的问题,它导致模拟器在每次连续构建后加载的时间越来越长,并且在几次加载后变得无响应。我的移动博览会应用程序也偶尔崩溃。我有一种模糊的感觉,这两个问题是相关的,但我完全不知道问题可能是什么。基本上每次我保存文件时,Exponent 模拟器的内存使用量都会翻倍。

这是 CreateEventScreen.js 目前的样子,我将在解决 onChange 问题后立即将其转换为 Redux。

export default class CreateEvent extends Component {
  constructor(){
    super();
    this.state = {
      name: '',
      date: new Date(),
      repeatAnnually: false,
      showDatePicker: false,
      wallPaperSource: null
    };
    this.toggleSelectWallPaper = this._toggleSelectWallPaper.bind(this);
    this.handleChange=this._handleChange.bind(this);
  }

  static navigationOptions = {
    title: 'Create New Event'
  }

  _handleToggleSwitch = () => this.setState(state => ({
    repeatAnnually: !this.state.repeatAnnually
  }));

  /* THIS IS NOT WORKING */
  _handleChange = (event) => {
    console.log(event);
    const target = event.target;
    const value = target.value;
    const name = target.name;
    this.setState({
      [name]: value
    })
  }

  _onDateChange = (date) => this.setState(state => ({
    date: date
  }));

  _toggleSelectWallPaper = async() => {
    let result;
    try {
      result = await ImagePicker.launchImageLibraryAsync({
        allowEditing: true,
        aspect: [4, 3]
      });
    } catch (e) {
        result = null;
    }

    if(!result.cancelled){
      this.setState({
        wallPaperSource: result.uri
      });
    }

  }

  _renderDatePicker(){
    if(this.props.showDatePicker){
      return (
          <DatePickerIOS
            date={this.state.date}
            mode="date"
            onDateChange={this._onDateChange}
          />
      )
    } else {
      return null;
    }
  }

  render(){
    const { onClick, toggleDatePicker, showDatePicker } = this.props
    let { wallPaperSource } = this.state;
    return(
      <View>
        <TextInput
          style={styles.input}
          name="name"
          placeholder="Event Name"
          value={this.state.name}
          /* THIS IS NOT WORKING */
          onChange={this._handleChange}
          /* This works but not ideal for redux integration */
          // onChange={(event) => this.setState({'name': event.target.value})}  
        />
        <View style={styles.eventDetailsContainer}>
          <View style={styles.itemContainer}>
            <Text>Repeat Annually</Text>
            <Switch
              onValueChange={this._handleToggleSwitch}
              value={this.state.repeatAnnually}
            />
          </View>
          <TouchableOpacity onPress={e => {
            e.preventDefault()
            toggleDatePicker(showDatePicker)
          }}>
            <View style={styles.itemContainer}>
              <Text>Select Date</Text>
              <Text>{this.state.date.toLocaleDateString()}</Text>
            </View>
          </TouchableOpacity>
          <View>
            {this._renderDatePicker()}
          </View>
        </View>
        <View style={styles.eventDetailsContainer}>
          <TouchableOpacity onPress={this.toggleSelectWallPaper}>
            <View style={styles.itemContainer}>
              <Text>Wallpaper</Text>
              { this.state.wallPaperSource  ?
                <Image source={{ uri: wallPaperSource }} style={{ width: 100, height: 100 }}/>
                 : null
              }
            </View>
          </TouchableOpacity>
        </View>
        <Button
          style={styles.submitBtn}
          onPress={e => {
            e.preventDefault()
            if(!this.state.name.trim()){
              return
            }
            onClick(this.state)
          }}
          color="#1e90ff"
          title="Create Event"
        />
    </View>
    )
  }
}

package.json -

{
  "name": "floss-evens",
  "version": "0.0.0",
  "description": "Hello Expo!",
  "author": null,
  "private": true,
  "main": "node_modules/expo/AppEntry.js",
  "dependencies": {
    "expo": "^18.0.4",
    "lodash": "^4.17.4",
    "moment": "^2.18.1",
    "prop-types": "^15.5.10",
    "react": "16.0.0-alpha.12",
    "react-native": "https://github.com/expo/react-native/archive/sdk-18.0.1.tar.gz",
    "react-native-image-picker": "^0.26.3",
    "react-navigation": "^1.0.0-beta.11",
    "react-redux": "^5.0.5",
    "redux": "^3.7.2"
  }
}

任何帮助或反馈将不胜感激。谢谢!

【问题讨论】:

  • 您是否有不想使用onChangeText 的原因?只是猜测,但事件对象可能很大,简单地记录它可能会停止其他 js 执行。如果您删除console.log,是否可以解决无响应问题?
  • 我不使用OnChangeText 的理由是它不是很可重用,因为我必须手动设置正在更新的密钥。另外,我认为当我在这个组件中实现 redux 时它会变得更加复杂。您删除console.log 是正确的!谢谢你。 onChange 事件有效。但是现在我正在记录目标console.log('target', event.target),它给我的所有输入都是“47”。
  • 好的。这也可以通过向onChangeText:onChangeText={(value) =&gt; this._handleChange(value, 'keyName')} 提供附加参数来解决。一个 redux 集成不应该改变这个逻辑,只会让信息流链更长。
  • 是的,我想我可以用onChangeText 来做,但我更喜欢动态地做,而不是传入静态值。感谢您的帮助。

标签: javascript react-native redux expo


【解决方案1】:

提供给onChange 的事件对象很大,如果记录,将停止其他 js 执行。只需删除console.log(event);

使用onChange 时,可以使用event.nativeEvent.text 检索输入值。但是,这不是您应该捕获输入值的方式。正确的做法是使用onChangeText

TextInput 没有名为 name 的属性,它将被简单地忽略。

// This will not be defined
const name = target.name;

您可以向_handleChange 提供额外的参数来完成预期的操作:

onChangeText={(value) => this._handleChange(value, 'keyName')}

如果您想自动处理此问题,例如对于大量输入,请参阅this question

【讨论】:

    猜你喜欢
    • 2018-09-11
    • 2019-02-28
    • 2021-03-25
    • 2022-12-22
    • 1970-01-01
    • 2020-02-23
    • 2020-01-31
    • 1970-01-01
    • 2021-03-29
    相关资源
    最近更新 更多