HNHacker News
TopNewBestAskShowJobs

christianalfoni

24 karma · joined November 19, 2015

submissionscomments
christianalfoni··on Let us replace community with AI
We are all feeling the pressure of generating code with AI for short sighted productivity gains. And with that the increase of cognitive debt, constant context switching and verbose plans nobody really reads. It creates a world with less human collaboration, joy of crafting and supporting communities.

This is not an extension trying to solve anything. It is just the only way I can express my discomfort with what is happening. We used to have a rhythm of moving between our crafted code and community to help us move forward. Waiting for AI generated code while doom scrolling AI generated tik tok is as dark as it gets, but it has very much become a reality.

christianalfoni··on Impact BETA invitation – React nested stores
Built on React context, use any reactive primitive you want and get concurrent safe, automatic observation in components and fast refresh support for your stores
christianalfoni··on Complex state management in React [video]
Ah, 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 :)

christianalfoni··on Complex state management in React [video]
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.

christianalfoni··on Complex state management in React [video]
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 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 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 :)

christianalfoni··on Complex state management in React [video]
Hi Sebastian and thanks so much for your feedback :)

1. So with observation an `ObserverContext` is created when using a store in a component. This "ObserverContext" tracks what signals you access in the component. This "ObserverContext" has to end its tracking when the component function exits. This is what `using` does. It runs logic when the component function exits to stop tracking signals. Then indeed we run a `useEffect`, or rather `syncExternalStore`, subscribing to the `ObserverContext` created. Traditionally you would have to wrap your component function in a higher order component, but then you have an additional import and you have to define your components as variable assignments. This also affects debugging as your components are typically not named with this signature. So yeah, think of `using` as "tracking signal access in the component scope" :)

2. So until now I have not been in a scenario where you would need to do this. Either you use a "key" on the `StoreProvider` to unmount and mount with new props. Which makes sense if the prop for example represents a user or a ticket in a project management app. Typically subscriptions created internally in the store would be its dynamic nature. That said, this does bring up a very interesting idea. We could make the props signals. So you would access the props in a store like any other signal you define in the store. I need to reflect a bit more on it and create a POC, but it is something we should implement before the official release as it would be a breaking change later. Thanks a bunch for this perspective!

3. A bit of text was lost there, but as I understand you suggest giving first class support for traditional Observables in signals? And you mean RxJS types of observables? I did reflect on this early on. Like Angular has a `toSignal` on their observables. This is something that can easily be added later given that we find a good way to execute on it. I'll experiment some more on this, thanks for bringing it up :)

4. Impact is considered a much lower level API than traditional global state management. So if you want to synchronise a signal with a url or local storage you would currently have to do that manually. But as a lower level API I hope to see people build abstractions. For example there could be a local storage sync API that looks like:

``` function MyStore() { const count = signal(0) const flag = signal(false)

  syncLocalStorage('$SOME-KEY', { count, flag })

  return {
    get count() {
      return count()
    },
    get flag() {
      return flag()
    }
  }
} ```

In this case the `syncLocalStorage` would be a two way sync with local storage. You define the initial signals and then any changes to them will be synced to local storage. Any changes in local storage is synced back to them, including any initial value. When the store unmounts, the sync is disposed of.

But yeah, I am not sure to what degree these things should be added to the library (It adds maintenance cost which I have been hurt by before). I want to first see if the community sees these opportunities and creates abstractions :)

Again, thanks a bunch for the feedback, I hope my responses made sense and have a great day!

christianalfoni··on Complex state management in React [video]
Impact is currently in release candidate and aims to solve some key pain points moving to global state management. With React 19 and new async patterns this library at the very least has some relevant perspectives.
christianalfoni··on Overmind.js – Frictionless State Management
Exactly! :)

It is very difficult to convey "When does this solution pay back its cost". If you can get by with only React as state management, great. There are so many factors that ties into friction. Everything from the experience of the team, preferences, size of project, how clear the domains of the project is, ability to separate and isolate, typescript or not etc.

christianalfoni··on Overmind.js – Frictionless State Management
Hi there and thanks for the feedback on "Why even choose this". Will update the front page!

But to answer your question.

The main reason Overmind and its predecessor Cerebral (https://cerebraljs.com/) was developed is application insight. The complexity of what we build on the web these days is way beyond the scope of what our brains are able to comprehend. What effects are triggered and what state changes are made is difficult to infer reading code and using low level debugging tools. Basically understanding what actually happens when you open the browser and interact with the application. So the main reason Overmind should catch your interest is its debugger. It is not there just to debug errors, it is there to constantly give you a mental image of the whole application at the abstraction level of the application itself.

The second reason Overmind was developed is to reduce the amount of concepts of APIs required to get going with an application. Most developers, arguably, think about code imperatively. "I have this thing I want to do, let me just do it". That is why Overmind has a base concept of an "action", where you can access any state, effects and other actions you have defined in your application... and just do it. This, arguably, lowers the threshold of understanding and scaling up your app. When you get into concepts related to time complexity Overmind provides operators. When you get into concepts related to state complexity Overmind provides statemachines and statecharts. It is important to understand that Overmind does not let you just free wield state changes. You can only run state changes in actions and unlike Mobx you can use async code as normal. The state changes are bound to the action execution itself, again creating a more straight experience with less concepts to learn.

The third reason is TypeScript. We have all felt the pain of Redux boilerplate and with TypeScript it does not become better. Overmind has the goal for you to spend as little effort as possible telling TypeScript about your application, it should just understand it. Basically help developers move to TypeScript by gaining as much benefit as possible with as little typing as possible.

Now, Overmind was not built to send a message that mobx-state-tree and redux are bad solutions. It is intended to be a healthy alternative in the ecosystem showing that controlled mutability is a valid approach and hopefully be an inspiration that we can push visual tooling way beyond what we are doing currently.

To get more details on controlled mutation VS value comparison (immutability) I wrote an article here: https://itnext.io/updating-uis-value-comparison-vs-mutation-...

christianalfoni··on Making Elm faster and friendlier in 0.16
This is really interesting, we have very different perspectives on how to consume how an application works. Not saying you are wrong at all, just have different perspective :)

1. When I say "global state" I mean the actual state, actions and signals are state changers, not state. A global state store looks like this:

{ admin: { users: [], showConfig: false }, home: { isLoadingNotifications: false, notifications: [] } }

This is one file. If you use local state this example would be split into maybe 3 different files. I think we both agree it has to do with how many files you need to look into. And the amount of composition you need to do in your head.

2. It would be interesting to see Om Next in JavaScript syntax, too much brainpower going into trying to read Clojure :) Not because it is bad, just have not learned it

3. That is true, but now it is conceptually no different than signals/actions and for that very reason. You should look into a different file to read the state change. I think it is a good thing. State changes are often very complex, surprisingly complex. They should not be inside a component. I think a component should only be about rendering UI. State changes should be expressed by a different layer.

So what I think is interesting here is that we seem to look at the app from two completely opposite sides. I do not care about the components to understand my app, because they just express its output, the UI. My app is really the state defined and the way it changes that state. What I do care about though is having dumb components is that makes me able to do universal apps, just move my app to a new UI output like react-native etc.

It will be really interesting to see how Om Next affects the JavaScript community. We are good at getting ideas from other languages and practices, where Elm is a good example :)

Again, not stating that you are wrong about anything. It is nice to go into a component and understand how that component works. Its just in my experience really bad to use a "view" as a container for state and business logic. That said it is really important to be open minded and I hope to see us grab ideas from Om Next. Actually trying to inspire creator of Baobab to bring in some new ideas :-)

christianalfoni··on Making Elm faster and friendlier in 0.16
Hi there,

I do not quite agree with this. Though I acknowledge your sentiments :-)

1. Global state is easier to reason about. If you have a single state store expressed as a single object you only have to read one file to understand the complete state of your application. If you let local state express the state and the global state is invisible you have to look into all these local state files and compose the complete state in your head

2. When you define it as local state you risk conflicting with some state set in a different component

3. You still have to change state. If you define your state in your components you will also have to include all the state changing logic inside the component. Your components will become very hard to reason about. And what if two components uses the same state and both of them needs to update the state? You will need to put the same logic into two different components

4. You could say Relay fixes this, but Relay just handles one thing and that is state related to the server. We build applications that does a lot more than talking to the server. Changing the state of your application is a huge problem space and though Relay is cool technology I can not imagine anyone expressing and changing all their state using Relay. So you need some other concept(s) to change all the other state and multiple concepts for doing the same thing is harder to reason about

Personally I think local state is a bad idea and currently I also think Relay is too limited. When I jump into an application I need to reason about what state it handles. With a global state store I can do that. Then I need to know how that state can be changed. Ideally that should be one concept, but we usually have lots of concepts for changing state. Then I want to see how the UI is expressed. Components are great for that, except when they are filled up with state definitions and state changing logic.

So from my perspective I am also trying to contribute with a solution :-) www.christianalfoni.com/cerebral