9 ms·
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
by treis 4y ago
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 few seconds.
This is just doing it wrong. State should change in response to user inputs. Ultimately, React is f(newState) => UI. If that function isn't pure you're gonna have a bad time. It's hard to blame anyone though. The docs suck and most of the tutorials you find get it wrong one way or another.
That said, there's kind of a reason why functional programming isn't more popular. It can be hard to grok and there can be a significant performance overhead. There's also a reason why this sort of implicit programming isn't as popular as imperative style. It's hard to predict what the implicit behavior is and footguns abound.
- cetra3 4y agoThe example you highlighted as "doing it wrong" is pretty typical for an autosuggest component: Input updates trigger some request, which propagates to some list somewhere else in the dom. As it's loading, a spinner is shown, but when results are retrieved, they're updated again. Throw in apollo to the mix or some other request library, and context is used.
- treis 4y agoThink you're gonna have a bad time. Should be something like: function handleChange(e){ getAutoSuggestions() setLoadingState(true) } ^ Side effects happen in response to user input function getAutoSuggestionsCallback(resp){ setSuggestions(resp) setLoadingState(false) } ^ No side effects
- petilon 4y ago> Ultimately, React is f(newState) => UI. If that function isn't pure you're gonna have a bad time. React is not that at all. Unless your UI is very simple, React is not f(newState) => UI. React isn't functional. More on that here: https://mckoder.medium.com/why-react-is-not-functional-b1ed12a41323 https://mckoder.medium.com/why-react-is-not-functional-b1ed1...
- quickthrower2 4y agoYou are both right. React components should render based on state that is managed by React, such that the rendered output changes only if the state changes. The complicated bit is the handling of events and changing the state. Hence why you get Redux for state but there is no “Redux for views”
- the_gipsy 4y agoReact very heavily pushes "component lifecycle" events, since it was class based up until now with hooks. That is, changing the state in the view function itself. It's not wrong, it gives you one kind of separation of concerns: components. But "the view is a function of state" is completely misleading IMO.
- treis 4y agosetState 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.
- petilon 4y ago> 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.
- treis 4y agoFrom 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.
- schwartzworld 4y agoYou 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.
- jameshart 4y agoThe 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.
- metta2uall 4y agoIn 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).
- acemarke 4y agoGlad to hear RTK is working well for you! FWIW, we actually specifically recommend _against_ using sagas in almost all cases. Instead, we recommend using our RTK Query API for data fetching and caching, and the RTK "listener" middleware for reactive logic: - https://redux.js.org/usage/side-effects-approaches#recommendations https://redux.js.org/usage/side-effects-approaches#recommend...
- metta2uall 4y agoThanks, I wasn't aware RTK now has a saga-like "listener" feature - will look into it! What I like about sagas are their simplicity & power (once one understands how generators & effects work), plus the eventChannel feature which lets one integrate with non-redux events. Good TypeScript support is a problem though, and I've had to resort to typed-redux-saga :/
- acemarke 4y agoYeah, we specifically designed the listener middleware to do ~90% of what you could do in sagas, but with a smaller bundle size, simpler API, and better TS support: - https://redux-toolkit.js.org/api/createListenerMiddleware https://redux-toolkit.js.org/api/createListenerMiddleware - https://blog.isquaredsoftware.com/2022/03/designing-rtk-listener-middleware/ https://blog.isquaredsoftware.com/2022/03/designing-rtk-list... Event channels was something we intentionally _didn't_ try to replicate per se, and tbh I've never tried to use those myself. (But, I _suspect_ that you might be able to do something similar with listeners even though we don't have a specific replacement built into the listener middleware, and if you do I'd love to see an example in action!) If you get a chance to try out listeners in your project, I'd definitely appreciate feedback on how well they work out for you - whether they solve your current saga use cases, what cases they _don't_ handle, anything we can do to improve the listener API, etc.
- the_gipsy 4y ago> State should change in response to user inputs. Absolutely not only to user inputs, but any kind of event: response, websockets, push notification, worker task finished... a million things beyond the basic "click". > If that function isn't pure you're gonna have a bad time. Hooks let you deal with "component lifecycles" which make that function not pure. Only the most basic toy react components are pure, everything is about side effects IN your views.
- yathaid 4y ago>> 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. The clue is in if everyone is missing the point but you, may be start with more introspection. :) I will give an example of a side project I am working on. The homepage has two sub components, one when the user is logged in, one when the user is logged out. Now, when the user logs in, the state of the homepage parent component needs to change, the state of the nav bar needs to change etc. Your problem is in assuming newState is completely described locally which isn't always the case.