Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

They're technically not pure, but they're as close as we can get to functional-style state handling: declare dependencies upfront so the caller knows exactly what they'll get when they execute your function. Fully state-less code achieves basically nothing; you need to "escape the hatch" eventually to work with the rest of the architecture. Hooks are very beautiful escape hatches that let you deal with persistence without having to sacrifice the rest of your function's body to it.


Really well said.

And if you really wanted to make it 'pure', you could easily write a hook with an explicit return type that wraps the type of the initial value. If you're using typescript, you can then limit the possible types of the generic to only monads.

    type State<T> = val as T;

    const useStatex = <T>(initialState: T) => {
        const [state, setState] = useState(initialState);
        return [state, updateState] as [State<T>, (val: T) => void];
    }
This new hook, useStatex, has an explicit type definition that indicates something stateful is taking place. Same as Futures. You can take this even further in the typing limiting the generic to only allow certain types for the underlying values to be monads, or even more simply

    type State<T> = Promise<T> | Array<T> | Option<T>
So you avoid an extra layer of nesting like

    State<Future<Array<T>>>
Point is, there are lots of ways to easily resolve any its not pure! arguments same as any other functional programming concept

eta

The simplest way to limit the return type might even be to just do this

    const useStatex = <T extends Promise | Array | Option>(initialState: T) => {




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: