Проблема: React-Native - клавиатура закрывается при каждом нажатии клавиши для TextInput - PullRequest
0 голосов
/ 09 мая 2020

Полный отказ от ответственности для этого - я работал с React Native около недели или двух, и я подозреваю, что столкнулся с этой проблемой, не совсем понимая почему!

Проблема : При каждом нажатии клавиши в поле TextInput клавиатура закрывается автоматически и записывает только первое нажатие клавиши.

Ситуация: Я использую предварительно определенный массив по умолчанию для useState. Поля TextInput вызываются с помощью .map () в зависимости от текущего состояния. OnChangeText () обновляет состояние, чтобы зафиксировать изменения в массиве. Состояние обновляется при каждом нажатии клавиши.

Что пробовали:

  1. Добавление / удаление ключа для различных компонентов, используемых в .map ()
  2. Добавление keyboardShouldPersistTaps = 'handled' в ScrollView, в котором вызывается .map (), включая все другие доступные варианты

Кто-нибудь знает, из-за чего клавиатура закрывается при каждом нажатии клавиши , и как я могу предотвратить это, продолжая фиксировать изменения в полях TextInput в основном состоянии?

Фрагмент кода, над которым я работаю (я удалил некоторые из несвязанная деталь):

import React, { useState } from 'react';
import {
  View,
  Text,
  Button,
  TextInput,
  SectionList,
  SafeAreaView,
  TouchableOpacity,
  ScrollView,
  Modal,
} from 'react-native';
import { Picker} from '@react-native-community/picker';



//import custom components

import { styles, Break } from './MasterStyles';
import { inputData, ingredients } from './inputData';



function addNewLoaf() {

  const [ingredientsList, setIngredientsList] = useState(ingredients);
  const [selectedLoaf, setSelectedLoaf] = useState('Regular Loaf');
  const [flourModalVisibility, setFlourModalVisibility] = useState(false);
  const [newLoaf, setNewLoaf] = useState('');

  function IngredientsRecorder() {

    return (
      <View style={styles.ingredientsContainer}>
        <View style={{flexDirection: 'column'}}>
          <View>
            <Text style={styles.metricTitle}>
              Volume of Ingredients:
            </Text>
          </View>
          {
            ingredientsList.map(e => {
              if(e.isVisible && e.ingredient){
                return (
                  <View style={{flexDirection: 'row', alignItems: 'center'}} key={e.id}>
                    <View style={{flex:2}}>
                      <Text style={styles.metricText}>{e.name}:</Text>
                    </View>
                    <View style={{flex:3}}>
                      <TextInput
                        placeholder='amount'
                        style={styles.inputText}
                        keyboardType='number-pad'
                        value={e.amount}
                        onChangeText={value => ingredientsAmountHandler(value, e.id)}
                      />
                    </View>
                    <View style={{flex:1}}>
                      <Text style={styles.ingredientsText}>{e.units}</Text>
                    </View>
                  </View>
                )
              }
            })
          }
        </View>
      </View>
    )
  }



  const ingredientsAmountHandler = (text, id) => {
    // setAmount(enteredText);

    let newArray = [...ingredientsList]
    let index = newArray.findIndex(element => element.id === id)

    newArray[index].amount = text
    setIngredientsList(newArray)
  }


  return (
    <SafeAreaView style={styles.container}>
      <View style={styles.page}>
        <Text style={styles.titleText}>Add a New Loaf</Text>
        <Break />
        <View style={{flexDirection: 'row'}}>
          <TextInput 
            placeholder='What would you like to call your loaf?' 
            style={styles.inputText}
            onChangeText={loafNameInputHandler}
            value={newLoaf}
          />
          <Button title='Create Loaf' color='#342e29' onPress={addNewLoafHandler} />
        </View>
        <Break />
        <ScrollView styles={styles.page} keyboardShouldPersistTaps='handled'>
          <LoafSelector />
          <FlourSelector />
          <IngredientsRecorder />
        </ScrollView>
      </View>
      <Break />
    </SafeAreaView>
  );
}

  export { addNewLoaf }

1 Ответ

2 голосов
/ 09 мая 2020

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

let defaultTemp={editingIndex:-1,text:''}

let [temp,setTemp] = useState(defaultTemp); //We will store current being edited input's data and index

{
        ingredientsList.map((e,i) => {
          if(e.isVisible && e.ingredient){
            return (
              <View style={{flexDirection: 'row', alignItems: 'center'}} key={e.id}>
                <View style={{flex:2}}>
                  <Text style={styles.metricText}>{e.name}:</Text>
                </View>
                <View style={{flex:3}}>
                  <TextInput
                    placeholder='amount'
                    style={styles.inputText}
                    keyboardType='number-pad'
                    value={temp.editingIndex===i?temp.text:e.amount}
                    //the input got focus
                    onFocus={()=>setTemp({editingIndex:i,text:e.amount})}
                    //the input lost focus
                    onBlur={()=>{
                         ingredientsAmountHandler(temp.text, e.id)
                         setTemp(defaultTemp)
                    }
                    onChangeText={text => setTemp({text,editingIndex:i})}
                  />
                </View>
                <View style={{flex:1}}>
                  <Text style={styles.ingredientsText}>{e.units}</Text>
                </View>
              </View>
            )
          }
        })
      }
...