如何从 TextInput(onChange 或 onTextChange)创建一个 rxjs Observable
How to create an rxjs Observable from TextInput (either onChange or onTextChange)
我想根据在 React Native TextInput
组件上触发的更改事件创建一个可观察对象。 TextInput
附带了 2 个我知道的更改道具(onChangeText
和 onChange
)。据我所知,如果您想访问需要使用 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'));
我认为问题在于将 current
直接分配给 sqftRef
。尝试在不使用 current
的情况下定义它,但在创建 Observable
时使用 current
,如下所示:
const sqftRef = useRef();
然后在 useEffect
中创建 Observable
以确保 DOM 准备就绪:
useEffect(() => {
fromEvent(sqftRef.current, 'onChange').subscribe((value) =>
console.log(value)
);
});
好的,我在 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
组件之外的事件。
我想根据在 React Native TextInput
组件上触发的更改事件创建一个可观察对象。 TextInput
附带了 2 个我知道的更改道具(onChangeText
和 onChange
)。据我所知,如果您想访问需要使用 onChange
.
onChange
我对原生事件对象不是很了解。我正在尝试使用 fromEvent
.
首先,我在我的功能组件中创建了一个引用,如下所示:
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'));
我认为问题在于将 current
直接分配给 sqftRef
。尝试在不使用 current
的情况下定义它,但在创建 Observable
时使用 current
,如下所示:
const sqftRef = useRef();
然后在 useEffect
中创建 Observable
以确保 DOM 准备就绪:
useEffect(() => {
fromEvent(sqftRef.current, 'onChange').subscribe((value) =>
console.log(value)
);
});
好的,我在 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
组件之外的事件。