3 ms·
Hi again and thanks for this discussion :) Yes, what you are saying makes a lot of sense. And traditionally you would need to do some combination of a global s
by christianalfoni 2y ago
Hi again and thanks for this discussion :)
Yes, what you are saying makes a lot of sense. And traditionally you would need to do some combination of a global state store like Redux, react-query and custom hooks.
Impact does support a new type of asynchronous pattern with React, which I am very excited about. It is supported in React 18 using the polyfilled `use` hook in Impact, but with React 19 you can use the `use` hook of React itself. What this means is that you do not have to differentiate sync/async values in signals. Signals makes promises observable. So:
const data = signal(fetchData())
const count = signal(0)
Both are observable values, where the data promise can be consumed in components with the `use` hook or by checking its data.status property directly.
So instead of having to split your state management between redux, react-query and hooks you are now able to just think state and co locate it with the same primitives and abstractions using stores.
If you read the https://impact-react.dev/deep-dive/queries-and-mutations https://impact-react.dev/deep-dive/queries-and-mutations docs, you'll see how the low level usage of this is. I would expect someone to create a similar data store abstraction for Impact like react-query, to manage expiration etc. at a higher level, like:
const DataStore = createDataStore(...)
which allows you to:
function MyComponent({ id }) {
using dataStore = useDataStore()
const data = use(dataStore.fetch(id))
}
But unlike react-query it would be based on observable promises.
But yeah, I do not want to state that Impact should just "do everything", but it is a low enough abstraction to co locate all state management in the same abstraction, if that is a priority. It might still feel too low level at the moment, but I am very curious to see where it goes.
When it comes to RxJS types of observables it is possible to do the same as `toSignal` in Angular, but I am unsure if it should be a first class concept like promises. Maybe it should, but also something the community can build :)
Would love for you to read https://impact-react.dev/deep-dive/queries-and-mutations https://impact-react.dev/deep-dive/queries-and-mutations and give your thoughts. We refactored a part of our own application where we needed to:
1. Fetch data about the content (promise)
2. Use that to instantiate a process (promise)
3. But async instantiation of this process also emitted events during instantiation we wanted to display as part of loading the process
4. Finally mount state management for this data bound to the process
Previously these steps where multiple components, but with this new async pattern we where able to express it all in a single component, line by line, using a store. It blew my mind :)
- SebastianKra 2y agoI get what you're saying in that document, but I would still prefer react-query. Although your example seems simple enough, it would become increasingly complex once you think about swr, caching, persistence, invalidation-timers etc... Requiring everything to be based on your low-level implementation seems like a tall ask. One thing that I love about React is how easily it can be configured to read from any reactivity-solution. This makes it possible to integrate pre-existing code or libraries. In impact, I see two possible clean entry points for external state: the Provider props, or a signal constructor similar to useSyncExternal store. I did some experimentation to see if I can write a function that converts an rxjs stream to a signal, but it involved multiple dirty hacks such as extracting the resolve/reject functions from the promise callback.
- christianalfoni 2y agoYeah, 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