3 ms·
I have been coding in react full time for the last 8 months in large codebases. I have to say that initially hooks were hard to understand especially useEffect
by faizshah 5y ago
I have been coding in react full time for the last 8 months in large codebases. I have to say that initially hooks were hard to understand especially useEffect but then as I got comfortable with them they were great to use and I was really productive. But then, as I started shipping production code with react I found that hooks are extremely difficult to debug and very complex to wrap your head around when debugging because of side effects and implicit behavior.
I now really dislike hooks because of the amount of implicit behavior and useEffect poisons the codebase to add even more implicit behaviors/side effects to your application.
They make the rendering behavior really difficult to reason about. I caught a bug where you had to click a button twice and the reason why it happens is extremely difficult to reason about: https://stackoverflow.com/questions/58106099/react-onclick-not-firing-on-first-click-second-click-behaves-as-expected-simpl https://stackoverflow.com/questions/58106099/react-onclick-n...
In my opinion what we need is an explicit state machine of the rendering of a component like vue’s component lifecycle. And these hooks we are using for state management we should instead use xstate to make the state transitions of a component explicit. React hooks (and redux and react-query) are bad (in my opinion) because they are easy to write with and hard to reason about.
- wldcordeiro 5y agoI think that the React devtools haven't kept up with how hooks work. They let you look at your props and state as they are now but not look at the "timeline" like something like the Redux devtools do. My struggle debugging is always trying to look at intermediate states and only having the current app state available, pausing the debugger didn't work as the React devtools crash when you do that.
- imbnwa 5y agoCan you expand on Redux? My gripes w/ Redux is that its pattern is clearly better suited to a runtime with more to offer functional programming than first-class functions, hence all the boilerplate and effort to abstract all that boilerplate, as well as deciding how to pick how you'll get to granular updates (which is where, from where I'm standing, React Hooks' design starts). But in comparison to React Hooks, its vastly superior for affording clear separation of boundaries in an app.
- faizshah 5y agoSo maybe I’m not the best person to speak specifically on redux as we use redux sagas so I can’t give a fair take on redux itself. However my gripe with redux sagas and react query is pretty simple, react query is implicitly defined implicit behavior, redux sagas is explicitly defined implicit behavior and xstate is explicitly defined explicit behavior. What do I mean by that? The applications that I work on do a lot of composition of apis, reshaping the data and caching on the frontend since our backend teams are micro services teams. What happens is that our codebase needs to define multi api workflows and data transformations which we define using redux sagas or react query (we either adopt one or the other for the codebase). The problem with the react query way of doing this is that the query has its own built in lifecycle it goes through stale -> fetching -> loading -> success/fail this is implicit behavior that you don’t have visibility into why it is making a transition. It becomes very painful for large workflows of api compositions to debug this kind of implicit behavior. Redux sagas on the other hand is explicitly defined. We have these channels of communication over which messages are defined (actions) which cause some explicitly defined behavior to happen (sagas, reducers). Now why is this problematic? In a large codebase of micro services transactions we are dispatching actions in response to a parent action forming an explicitly defined implicit behavior. So for example with react query if I am debugging an unexpected state in prod for a bug I have to reason about the way react query is processing a query in order to debug it due to the implicit behavior. In redux sagas world I have to reason about the implicit state machine of actions, sagas and reducers that a workflow kicks off. This is why I don't like these two styles of organizing the application state. It becomes difficult to reason about the behavior but the redux/redux sagas way is easier to reason about because at least we explicitly defined the implicit behavior. Also make sure to note I am talking about a complex web app on a micro-services api (frontend does a lot of api composition work), I am sure these are elegant solutions in the right context.
- pault 5y ago> What do I mean by that? The applications that I work on do a lot of composition of apis, reshaping the data and caching on the frontend since our backend teams are micro services teams. You may want to consider whether you're doing the back end devs' work for them. :) I'm a FE dev working with a lot of microservice back ends for the last 3 years, and a realization that I had early on was that the back end devs were reducing the back end complexity by pushing it into the front end. Whenever I find myself writing transaction logic for an operation that cuts across multiple services, I suggest we use a backend for frontend (BFF) service that performs those transactions instead. There is an incredible amount of complexity in the front end already, and things like read/write transactions and data consistency are not front end concerns. At my current gig we use an event driven saga architecture[0] (inspired by but no relation to redux-saga) to keep multi-service transactions out of the front end, and it just feels like everything is where it should be. Instead of using a front end saga, the front end sends a graphql mutation to a back end saga and gets back a transaction id, which it can subscribe to and get status updates on the transaction (ie. state and errors). It wouldn't make sense to have your back end devs manage the state of a dropdown, so why are they always asking us to manage their data transactions? :) [0]: https://github.com/social-native/kafka-sagas https://github.com/social-native/kafka-sagas (this is a purely back end library; the front end queries the saga state with plain graphql operations).