Live data from Hacker News

React is holding me hostage

emnudge.dev

51–60 of 553 posts

Re: React is holding me hostage

#51
post #40
post #37

Earlier quoted context omitted.

setState is a convoluted way of passing the newState to components. useEffect is a side effect and if you use it you're gonna have a bad time.

> useEffect is a side effect and if you use it you're gonna have a bad time. Right.. but then you can't really use React for building serious UI.

From what I've seen that's like saying you need to use salt to be a good cook while pouring a bucketful on a salad. Perhaps it's technically true but from what I've seen you can build pretty complex UI without useEffect if you follow the rules.

Re: React is holding me hostage

#52
post #27

I've been working on a React side project for a few months now and looking at my company's apps plus posts like this I think people just miss the point. Stuff like this: >Things get more complicated when you start using React Context and start signalling updates in a parent component. The render cascades. Maybe one component fetches some data, some component remounts, and you run your state update again, delayed by a…

The bit of react that is f ( newState ) => UI is the easy part. The bit that is g ( state , userInput ) => newState is the hard part. In particular managing the scope of that newState . Oh, and sometimes you need to handle h ( state , asynchronousData ) => newState too. And then comes the fact that even though your f is _pure_, it also has to be _fast_, because it's going to run every time you get a newState .

In my experience redux-toolkit + redux-saga for async stuff usually work really well. In case of performance problems one can go with profiling + targeted optimisations (e.g. a separate store, some locally managed state).

Re: React is holding me hostage

#53
post #47
post #44

Earlier quoted context omitted.

The linked article doesn’t convince me, instead it shows a misunderstanding of react and hooks. > But then they added hooks and useState and useEffect and so on, which made the functions impure. The problem with hooks is that they “hook into” React state and lifecycle features, which means it is modifying global state. React components don’t update the dom every time they run, they update the fiber tree / virtual DOM…

> ...and capture a sequential list of updates when you call setState. In functional programming, functions are not allowed to do that. The only thing a function is allowed to do is return a value. > ... you reach out up the stack to the component and store it there. FP functions are not allowed to do that. In FP functions can only rely on the parameters passed to it (it cannot refer to anything outside) and it should…

> In functional programming, functions are not allowed to do that. The only thing a function is allowed to do is return a value.

Oh, yes, they are allowed to do that. You capture the effects into a list, and return the tuple of list and return value. If you feel like it, you wrap that into a monad to pretend you are only "returning" a single thing.

> In FP functions can only rely on the parameters passed to it (it cannot refer to anything outside) and it should not do anything beyond return a value.

You mean explicit parameters (props) and implicit parameters (context), right? I thing you forgot the latter. Implicit parameters have existed for quite a bit, for example in the reader monad.

> In FP, functions can be called in any order (unless one function needs the return value of another), and the final result is not affected by the order.

Yup, except if you write a bunch of functions and store them in a list with the intention of applying the result of the first entry of the list against the first entry of the list. Now, if you construct the list of functions as effects (by hiding them behind a monad) you find out that you need to call the effects in the same order as to construct the list of effects in the same order. This doesn't contradict FP, it contradicts your mental model of how React is supposed to work.

> If you have state it is not FP, whether it is global or not.

The state resides in the runtime executor, exactly like Haskell's IO monad. Again, this contradicts your mental model, not React or FP.

Re: React is holding me hostage

#54
post #47
post #44

Earlier quoted context omitted.

The linked article doesn’t convince me, instead it shows a misunderstanding of react and hooks. > But then they added hooks and useState and useEffect and so on, which made the functions impure. The problem with hooks is that they “hook into” React state and lifecycle features, which means it is modifying global state. React components don’t update the dom every time they run, they update the fiber tree / virtual DOM…

> ...and capture a sequential list of updates when you call setState. In functional programming, functions are not allowed to do that. The only thing a function is allowed to do is return a value. > ... you reach out up the stack to the component and store it there. FP functions are not allowed to do that. In FP functions can only rely on the parameters passed to it (it cannot refer to anything outside) and it should…

I find it's best (if side effects and state mutation make you nervous) to think of hooks as essentially part of the function signature of a react component, both on the parameter side, as well as on the return side. They are not written as such, because of syntactic limitations of JavaScript, but essentially a react component that starts off like this:

   function MyComponent({}) {
      const [count, setCount] = useState(0);
      const [active, setActive] = useState(true);
      useEffect(() => if (active) setTimeout(1000, () => setCount(count+1)), [count, active]);
      ...
can kind of be thought of as if it accepts an extra hidden set of parameters, kind of like this:

   function MyComponent({}, hook1 : useState, hook2 : useState, hook3 : useEffect) {
      const [count, setCount, hook1Result] = hook1(0);
      const [active, setActive, hook2Result] = hook2(true);
      const hook3Result = hook3(() => if (active) setTimeout(1000, () => setCount(count+1)), [count, active]);
      ...
      return [, [hook1Result, hook2Result, hook3Result]];
   }
In this version, those hook functions are side-effect free, pure functions that our caller provides us with, closed over the previous stored state of our component in the tree; and when we return the results along with our rendered output, our caller has the new state of our component together with our desired DOM.

Instead of forcing us to write all that extra code, route those extra variables, and figure out the metadata mechanism whereby the caller of the render method figures out what hook functions to supply, the rules of hooks let you use JavaScript's imperative, procedural syntax to call hooks which are implemented using ugly side-effecting impure techniques, but in a way that pulls off something semantically identical to this pure functional flow.

It's a pretty neat trick, honestly.

Re: React is holding me hostage

#55
post #40
post #37

Earlier quoted context omitted.

setState is a convoluted way of passing the newState to components. useEffect is a side effect and if you use it you're gonna have a bad time.

> useEffect is a side effect and if you use it you're gonna have a bad time. Right.. but then you can't really use React for building serious UI.

You have to use it, obviously, but it should be used for side effects primarily. A good indicator is if all the values in your dependency array are react props/state, you're doing it wrong.

Re: React is holding me hostage

#56
post #47

Earlier quoted context omitted.

> ...and capture a sequential list of updates when you call setState. In functional programming, functions are not allowed to do that. The only thing a function is allowed to do is return a value. > ... you reach out up the stack to the component and store it there. FP functions are not allowed to do that. In FP functions can only rely on the parameters passed to it (it cannot refer to anything outside) and it should…

I find it's best (if side effects and state mutation make you nervous) to think of hooks as essentially part of the function signature of a react component, both on the parameter side, as well as on the return side. They are not written as such, because of syntactic limitations of JavaScript, but essentially a react component that starts off like this: function MyComponent({}) { const [count, setCount] = useState(0);…

Don't call this functional programming. If you call setCount() then this is not functional because your function is doing something besides returning a value. In fact, it is setting state, which is against FP principles.

Re: React is holding me hostage

#57
post #36

Meh. The most important thing about React is you have to think like React wants you to. It's a very pattern-oriented type of development I haven't seen much of elsewhere. Most of the footguns listed in this article are things you obviously shouldn't want to do because they're not React-y.

Some others would describe it as idiom-orientated.

Re: React is holding me hostage

#58

Earlier quoted context omitted.

There is context which wages a war against debugging and testing, for one thing. React has no real answer to state going sideways. Then there is controlled/uncontrolled component which is an example of structural instability (what looks like a tiny change to your boss is a bigger deal than it should be) unless you ride the crazy train and use “plain ordinary javascript” to build a parallel system to move (some of) th…

If you are having trouble testing context, you are _definitely_ doing context wrong. To test the context itself: pass as children of the context components to render the context state. To test the components within the context: create a context with mock functions/values. React has no answer to state going sideways because React manages a tree of components, and you are not supposed to connect random branches of a tr…

For the goals of the application you can push a button in one branch of the tree and it has an impact on many other branches…

Re: React is holding me hostage

#59
post #47

Earlier quoted context omitted.

> ...and capture a sequential list of updates when you call setState. In functional programming, functions are not allowed to do that. The only thing a function is allowed to do is return a value. > ... you reach out up the stack to the component and store it there. FP functions are not allowed to do that. In FP functions can only rely on the parameters passed to it (it cannot refer to anything outside) and it should…

> In functional programming, functions are not allowed to do that. The only thing a function is allowed to do is return a value. Oh, yes, they are allowed to do that. You capture the effects into a list, and return the tuple of list and return value. If you feel like it, you wrap that into a monad to pretend you are only "returning" a single thing. > In FP functions can only rely on the parameters passed to it (it ca…

I think you may be missing the forest for the trees. The point of FP is that you can glance at a function and say 'this is obviously correct' without having to work out the state and context of every call.

Re: React is holding me hostage

#60
post #56

Earlier quoted context omitted.

I find it's best (if side effects and state mutation make you nervous) to think of hooks as essentially part of the function signature of a react component, both on the parameter side, as well as on the return side. They are not written as such, because of syntactic limitations of JavaScript, but essentially a react component that starts off like this: function MyComponent({}) { const [count, setCount] = useState(0);…

Don't call this functional programming. If you call setCount() then this is not functional because your function is doing something besides returning a value. In fact, it is setting state, which is against FP principles.

Okay. But is it against FP principles to write software that runs in web browsers then?

Because web browsers exist, and they work in a nonfunctional way.

So to interact with one we need to do a little bit of imperative code.

And then react lets us figure out what to do when the web browser responds to that imperative code by letting us run a largely functional program.

Which is pretty neat considering we’re doing so in JavaScript.

The thing that we’re after here is not a badge that we can slap on our code saying ‘certified 100% functional’. We are trying to write code using patterns that help us reason about and structure what we want the computer to do, avoid bugs, and ship software.

If react managed to squeeze a surprisingly functional pattern into a JavaScript library to that end, can’t we just applaud the audacity and enjoy using it, without nitpicking that they didn’t actually reimplement the lambda calculus?

Post reply on HN