#reactjs #react-native #expo #textinput
#reactjs #react-native #выставка #ввод текста
Вопрос:
У меня проблема в том, что когда я отправляю спам, вводя текстовый ввод, и нажимаю кнопку, чтобы отправить и очистить текст, он становится лагающим и не сразу очищает текст в текстовом вводе. Это происходит, когда у меня на экране много содержимого (например, текст Lorem Ipsum).
Это проблема для меня, потому что я разрабатываю приложение для чата, и всякий раз, когда журнал чата большой, а пользователи быстро вводят и отправляют сообщение, оно не будет очищено немедленно и все равно останется в TextInput, что является плохим юзабилити. Я попробовал это с помощью ref и контролируемого ввода текста (без разницы).
Вы можете увидеть проблему в моем gif:
Вот закуска для expo, чтобы воспроизвести проблему: https://snack.expo.io/s22hVf140
Это мой код:
Мои сообщения:
const MyMessages = () => {
const [messages, setMessages] = useState([]);
const addMessage = (text) => {
const arr = [text, ...messages];
setMessages(arr);
};
return (
<View>
<MyTextInput addMessage={addMessage}></MyTextInput>
{messages.map((msg, i) => {
return <Text key={i}>{msg}</Text>;
})}
<Text>
Lorem ipsum.......
</Text>
</View>
);
};
MyTextInput:
const MyTextInput = ({ addMessage }) => {
const [text, setText] = useState("");
const myRef = useRef();
const submit = () => {
myRef.current.clear();
addMessage(text);
};
return (
<View>
<TextInput
ref={myRef}
style={{
width: "100%",
height: 50,
backgroundColor: "lightgrey",
marginTop: 50,
}}
onChangeText={(text) => setText(text)}
></TextInput>
<Button title="submit" onPress={submit}></Button>
</View>
);
};
У кого-нибудь есть идея, почему это происходит с большим содержимым на экране?
Комментарии:
1. Рассматривали ли вы возможность использования виртуализированного списка, например
FlatList
, для отображения каждого элемента чата в журнале? Это должно обеспечить некоторое повышение производительности рендеринга. Вы также должны использовать некоторые инструменты разработки, чтобы помочь определить, что вызывает «большую, чем ожидалось» нагрузку на рендеринг.2. @98sean98 эта проблема также возникает с FlatList. Я не мог понять, как правильно использовать инструмент разработки профилей, но это действительно весь мой код (см. Раздел, чтобы воспроизвести его)
3. У вас такая же проблема в производстве? Или только в режиме разработки?
4. Я проверил ваш код snack. Сначала я подумал, что ваш рендеринг можно улучшить, приняв во внимание, как работает алгоритм dom diffing от react . Но даже после того, как я добавил an
id
к каждому новому сообщению перед вставкой в массив, у него есть «задержка», на которую вы ссылаетесь. При ближайшем рассмотрении этого поведения это происходит только тогда, когда вы нажимаете отправить, одновременно вводя другой символ в поле. Таким образом, это означает, что обаsubmit
и(text) => setText(text)
были вызваны одновременно. Я пытался найти решение, но пока ничего.5. @98sean98 да, вы правы. Я «рад», что у вас также есть эта проблема. Это ошибка react native? Поскольку мой код действительно прост, и у меня все еще есть эта проблема…. Спасибо, что тоже нашли решение. 🙂
Ответ №1:
Поскольку submit
и onChangeText
обратные вызовы запускаются одновременно, когда нажатие клавиши и нажатие кнопки «отправить» происходят одновременно, я отменил submit
обратный вызов для запуска с задержкой в 100 мс.
См. раздел «Закуска на выставке«.
Библиотека use-debounce предоставляет элегантное решение для обработки подобных событий пользовательского ввода.
Я также устранил необходимость в a ref
, сделав TextInput
контролируемым путем передачи value={text}
prop.
Что касается того, почему TextInput
does not clear()
while addMessage()
успешно вызывается (без отмены), на данный момент у меня нет объяснения. Хотелось бы знать, может ли кто-нибудь указать.
Не удается решить проблему
После еще нескольких тестов на моем физическом устройстве я иногда наблюдаю нежелательное поведение.
Комментарии:
1. к сожалению, проблема все еще существует, я только что попробовал вашу закуску на своем устройстве, и это то же самое, когда спам набирает и отправляет одновременно. Я думаю, что подход должен заключаться в том, чтобы посмотреть, почему это происходит только с большим контентом. если на экране не так много содержимого, он работает нормально.
2. Хм… Я тестировал на своем iPhone SE 2, запустив клиент expo. Прошел тест одновременности, кажется, все в порядке. Символ появляется при вводе текста, затем отправляется текстовая строка.
3. На моем iPhone XS проблема все еще существует … кроме того, исходя из добавленной вами задержки, теперь у вас небольшая задержка при отправке текста, чтобы он отображался, чего я тоже не хотел бы, поскольку я хочу, чтобы это было быстро.
4. Возможно, единственным способом обойти эту проблему является минимизация задержки до <10 мс (реакция человека обычно находится в диапазоне 100-200 мс, поэтому все, что меньше 50 мс, должно быть едва заметным). Мое наблюдение за Whatsapp, делающим то же самое, также имеет небольшую задержку. Не уверен, совпадает ли эта задержка с тем, что я предложил здесь, но я не думаю, что пользователям будет все равно, если это «не очень заметно».
5. Несмотря на то, что проблема немного улучшилась, приложение теперь выглядит в целом менее гладко. И проблема все еще существует (задержка 10 мс): im2.ezgif.com/tmp/ezgif-2-1d19cf2325fe.gif