如何仅在光标移动但输入内容未变更时触发onSelectionChange事件
实现方案
核心思路为通过缓存上一次的输入文本和光标选区状态,在onSelectionChange触发时做双重校验,只有文本未变更、选区发生变化的场景才执行业务逻辑。
具体实现步骤
- 声明两个状态分别缓存上一次的输入文本
prevText、上一次的光标选区prevSelection - 在
onChangeText回调中同步最新输入文本到状态 - 在
onSelectionChange回调中先判断当前文本是否和prevText相等:- 不相等:说明本次触发由文本变更(输入/删除/粘贴等)导致,直接更新
prevText和prevSelection缓存后返回,不执行业务逻辑 - 相等:再判断当前选区和
prevSelection是否不一致,不一致则说明是纯光标移动,执行@提及相关业务逻辑,之后更新prevSelection即可
- 不相等:说明本次触发由文本变更(输入/删除/粘贴等)导致,直接更新
代码示例
import React, { useState } from 'react'; import { TextInput } from 'react-native'; const MentionInput = () => { const [text, setText] = useState(''); // 缓存上一次的文本和选区状态 const [prevText, setPrevText] = useState(''); const [prevSelection, setPrevSelection] = useState({ start: 0, end: 0 }); const handleSelectionChange = (e) => { const currentSelection = e.nativeEvent.selection; // 文本发生变更,直接更新缓存后返回,不执行业务逻辑 if (text !== prevText) { setPrevText(text); setPrevSelection(currentSelection); return; } // 文本未变更,且选区发生变化,说明是纯光标移动/选区调整 if (currentSelection.start !== prevSelection.start || currentSelection.end !== prevSelection.end) { // 此处写入@提及相关业务逻辑 console.log('仅光标移动,触发业务逻辑', currentSelection); setPrevSelection(currentSelection); } }; return ( <TextInput value={text} onChangeText={setText} onSelectionChange={handleSelectionChange} multiline style={{ height: 100, borderWidth: 1, padding: 8 }} /> ); }; export default MentionInput;
注意事项
- 该方案兼容所有文本变更场景:包括输入、删除、剪切、粘贴等操作导致的选区变化,都会被正常过滤
- 支持长按选中文本的场景识别,选中文本时文本内容未变更仅选区范围变化,会正常触发业务逻辑
- 受控组件场景下需确保
text状态更新逻辑正常,避免出现状态不同步导致的判断错误
内容的提问来源于stack exchange,提问作者Talmacel Marian Silviu
相关产品推荐
相关产品推荐

