Реакт-Натив Экспо с TextInput

1

Я создаю приложение для отслеживания событий, использующее React-Native, Redux, React-Navigation и Expo, и у меня проблемы с довольно тривиальной частью.

У меня есть экран формы, где вы вводите имя события, дату и другую информацию. Я использую <TextInput/> для ввода имени события, но не будет иметь значение onChange, только onChangeText. Кроме того, когда я использую событие onChange, кнопка " Назад" в навигации становится неактуальной, и курсор остается только в TextInput независимо от того, где я нажимаю

У меня возникает другая проблема, связанная с памятью, которая заставляет симулятор загружаться дольше и дольше после каждой последовательной сборки и перестает отвечать после нескольких нагрузок. Иногда мое мобильное приложение-экспонат также вылетает из строя. У меня есть несколько смутное чувство, что эти два вопроса связаны, но я полностью потерял то, что может быть проблемой. В основном имитатор Exponent удваивает использование памяти каждый раз, когда я сохраняю файл.

Вот как выглядит CreateEventScreen.js на данный момент, я собираюсь преобразовать его в Redux, как только я разрешу проблему onChange.

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"
  }
}

Любая помощь или обратная связь были бы весьма признательны. Спасибо!

  • 0
    Есть ли причина, по которой вы не хотите использовать onChangeText ? Просто предположение, но объект события может быть огромным, и простое ведение журнала может остановить выполнение других js. Если вы удалите console.log , решит ли это проблему отсутствия ответа?
  • 0
    Моя OnChangeText не использовать OnChangeText том, что он не очень многократно используется в том смысле, что мне придется вручную устанавливать обновляемый ключ. Кроме того, я думаю, что будет сложнее, если я добавлю в него избыточность этого компонента. Вы были правы относительно удаления console.log ! Спасибо тебе за это. Событие onChange работает. Однако теперь я регистрирую целевой console.log('target', event.target) и все, что он мне дает, это "47" для любого ввода.
Показать ещё 2 комментария
Теги:
react-native
expo
redux

1 ответ

1
Лучший ответ

Объект события, onChange в 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')}

Если вы хотите обработать это автоматически, например, для большого количества входов, см. Этот вопрос.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню