如何从 TextInput(onChange 或 onTextChange)创建一个 rxjs Observable

How to create an rxjs Observable from TextInput (either onChange or onTextChange)

我想根据在 React Native TextInput 组件上触发的更改事件创建一个可观察对象。 TextInput 附带了 2 个我知道的更改道具(onChangeTextonChange)。据我所知,如果您想访问需要使用 onChange.

的本机事件,则需要使用 onChange

我对原生事件对象不是很了解。我正在尝试使用 fromEvent.

创建一个 rxjs observable

首先,我在我的功能组件中创建了一个引用,如下所示:

const sqftRef = useRef().current

然后我将此 ref 附加到 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 (evaluating target.addEventListener):

fromEvent(sqftRef, 'onChange').subscribe(value => console.log(value))

我知道我的做法是错误的。希望有人能给我指出正确的方向。

我会将您需要的事件发送到一个主题中,然后在您的代码的其他部分订阅该主题。

这是一个简单的 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

我认为问题在于将 current 直接分配给 sqftRef。尝试在不使用 current 的情况下定义它,但在创建 Observable 时使用 current,如下所示:

const sqftRef = useRef();

然后在 useEffect 中创建 Observable 以确保 DOM 准备就绪:

useEffect(() => {
  fromEvent(sqftRef.current, 'onChange').subscribe((value) =>
    console.log(value)
  );
});

好的,我在 Amer Yousuf 和 A​​lex 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 组件之外的事件。