如何从 TextInput(onChange 或 onTextChange)创建 rxjs Observable
Posted
技术标签:
【中文标题】如何从 TextInput(onChange 或 onTextChange)创建 rxjs Observable【英文标题】:How to create an rxjs Observable from TextInput (either onChange or onTextChange) 【发布时间】:2021-10-28 04:40:52 【问题描述】:我想根据在 React Native TextInput
组件上触发的更改事件创建一个可观察对象。 TextInput
带有我知道的 2 个更改道具(onChangeText
和 onChange
)。据我所知,如果你想访问本地事件,你需要使用onChange
,你需要使用onChange
。
我对原生事件对象了解不多。我正在尝试使用 fromEvent
创建一个可观察的 rxjs。
首先我在我的功能组件中创建了一个引用,如下所示:
const sqftRef = useRef().current
然后我将此引用附加到TextInput
组件,如下所示:
<TextInput
ref=sqftRef // attach a ref
label='Sqft'
mode='flat'
textContentType='none'
autoCapitalize='none'
keyboardType='numeric'
autoCorrect=false
value=String(formValues.sqft)
dense
underlineColor=colors.colorOffWhite
onChangeText=(text) => setText(text)
onChange=e =>
// somehow create an observable from this event ???
style=styles.inputStyles
theme=inputTheme
/>
我尝试像这样使用 fromEvent 创建一个 Observable,但它不起作用。我得到 undefined is not an object(评估 target.addEventListener):
fromEvent(sqftRef, 'onChange').subscribe(value => console.log(value))
我知道我的方法全错了。希望有人能指出我正确的方向。
【问题讨论】:
【参考方案1】:我会将您需要的事件发送到主题中,然后在代码的其他部分订阅主题。
这是一个简单的 React 示例,可以帮助您入门
function App()
const textChange = new Subject<string>();
useEffect(() =>
// subscribe to
const subscription = textChange.asObservable().subscribe(console.log)
return () => subscription.unsubscribe()
, [])
// Emit events with a subject
return <textarea onChange=(e) =>
textChange.next(e.target.value)
>
</textarea>
render(<App />, document.getElementById('root'));
在此处查看示例:https://stackblitz.com/edit/react-ts-akoyfv
【讨论】:
我尝试了几种不同的方法。最初我得到这样的参考: const sqftRef = useRef().current 然后它总是参考电流。但是这并不能正常工作,因为据我所知,您必须将 ref 本身附加到 textinput,而不是当前值。当我使用您的解决方案时,我得到“无效的事件目标” @JoMomma 我用不同的想法更新了我的答案。它使用React而不是ReactNative,但原理还是一样的。 我不知道为什么,但是当我尝试像你这样的解决方案时,next() 函数只会在第一次触发....它没有完成或出错,但每隔一个下一个() 调用什么都不做。 我知道原因了。我将其添加到我的答案中。记住订阅很重要,这样它就不会在状态更改时重新创建。【参考方案2】:我认为问题在于将current
直接分配给sqftRef
。尝试在没有current
的情况下定义它,但在创建Observable
时使用current
,如下所示:
const sqftRef = useRef();
然后在useEffect
中创建Observable
以确保DOM 准备就绪:
useEffect(() =>
fromEvent(sqftRef.current, 'onChange').subscribe((value) =>
console.log(value)
);
);
【讨论】:
我也发现了这一点,但现在我得到一个错误:'无效的事件目标'。也许是因为它是***代码?在我尝试创建流之前,是否还没有附加参考?也许我会尝试在 useEffect 中设置它.... 是的,您应该在useEffect
中使用它。抱歉,我忘了提。【参考方案3】:
好的,我在 Amer Yousuf 和 Alex Fallenstedt 的帮助下解决了这个问题。
我做了类似于 Alex 建议的事情,修改了他的 React Native 解决方案。他的解决方案对我不起作用的一个原因是,使用useRef
挂钩来防止在每次渲染时重新创建 Observable 非常重要。如果 observable 被重新创建(在重新渲染时)并且 useEffect 没有再次运行,那么我们将没有对新(重新创建)的 observable 的活动订阅(useEffect 不再运行)。这就是为什么我对 sqft$.next 的调用最初只被调用一次(第一次直到我们重新渲染)。
我的解决方案如下所示:
let sqft$ = useRef(new BehaviorSubject(0)).current
useEffect(() =>
const sub = sqft$.subscribe(
next: (val) =>
// just testing stuff out here
updateForm('sqft', val)
updateForm('lot', val * 2)
)
// this is only relevant to my use case
if (activeReport) sqft$.next(activeReport.sqft)
return () => sub.unsubscribe()
, [activeReport])
当然,我将其称为onChangeText
:
onChangeText=(text) =>
sqft$.next(text)
所以这现在正在工作。我仍然觉得使用onChange(e => ...stuff)
可能有更好的方法。我会暂时保留这个问题,以防有人可以分解如何使用 nativeEvent 执行此操作,或者向我解释如何访问 TextInput
组件的事件。
【讨论】:
请问我建议的解决方案到底有什么问题? 它产生一个错误:“未定义不是一个对象(评估'target.addEventListener')。我不知道为什么。我们需要访问nativeEvent吗?我们有错误的事件名称('onChange')?我还不知道,但这个解决方案不起作用。以上是关于如何从 TextInput(onChange 或 onTextChange)创建 rxjs Observable的主要内容,如果未能解决你的问题,请参考以下文章