6 ms·
Yeah, I agree that is definitely a tall ask :) I just published a version with the signal props. Doing this made me realise that it creates this strong concept
by christianalfoni 2y ago
Yeah, I agree that is definitely a tall ask :)
I just published a version with the signal props. Doing this made me realise that it creates this strong concept that StoreProviders becomes the bridge between the reconciling world of React and the observable world of Impact. You have plain values going in as props, becoming signals in Impact. And you have signals going out of Impact, consumed as plain values in React.
So with react-query you would be able to just use that data fetching hook and pass data to a StoreProvider, where it becomes a signal. So you could have a store like:
```
function MyStore(props) {
const reactQueryData = props.data
effect(() => {
console.log(reactQueryData())
})
return {}
}
```
React will update that signal whenever react-query causes reconciliation and the value changed.
In case of RxJS I was thinking of doing something like:
```
function toSignal(rxJsObservable, initialValue) {
const value = signal(initialValue)
const subscription = rxJsObservable.subscribe(value)
cleanup(() => subscription.unsubscribe())
return value
}
```
So basically you give a signal a default value and subscribe to the updates, updating the signal. But as I understand RxJS there are several ways to think about these observables... hot/cold... single event, multiple events etc. etc. Not sure how to create a single abstraction over that.
- SebastianKra 2y ago> Doing this made me realise that it creates this strong concept that StoreProviders becomes the bridge between the reconciling world of React and the observable world of Impact Agreed, this feels quite intuitive to me as well. For rxjs & co I was trying to come up with a solution that could incorporate Suspense as well. Something like: function signalFromStream(stream) { const resolve, reject const emissions = signal(new Promise((res, rej) => resolve = res; reject = rej)) const unsubscribe = stream.subscribe((value) => { if (emissions.status = 'pending') resolve(value) else emissions(Promise.resolve(value)) }) cleanup(unsubscribe) return () => { emissions() } } but I'm not happy about constructing a promise and then constructing another promise for each subsequent emission. At least https://github.com/tc39/proposal-promise-with-resolvers https://github.com/tc39/proposal-promise-with-resolvers will help with with the first issue. Apart from that, I would consider this an acceptable solution - it's not much different from the useState+useEffect dance that you would have to do to integrate with React. Hot/Cold doesn't really matter here. If it's cold, it will begin emitting as soon as we execute this function. If it's hot, upstream is responsible for deciding when to send & stop sending. Side-note: I'm not actually trying to use rxjs in any of my current frontend projects. But the ubiquity of this observable pattern means that if you can integrate rxjs, you can probably integrate anything.
- christianalfoni 2y agoAh, I see! I have not worked much with RxJS observables, though I did implement dark/light mode on their previous website... and wrote some docs on how to use them for state management :-D But as I understand here you basically want the stream to represent an async value (promise), which makes a lot of sense to me. I have been in this promise challenge before and was not aware of the proposal, and already at stage 4! Great stuff! As signals are so low level, but has this first class async nature, I wanted to do some iterations on abstractions. Not to necessarily include in Impact, but as you are doing now... just see what kinds of abstractions makes sense on top of it. This was very inspirational, thank you! It is kinda funny how promises can easily be thought of as kind of a "transport for a state value". When it resolves you move that value into your state primitive of choice. But now the promise is not "a transport for a state value", it IS the state value. And suspense just emphasises that perspective. It is very interesting. Anyways, thanks again for your perspectives and input. For me it is as much getting the perspectives and terminology right, as the implementation itself :)