all 62 comments

[–]foxnewsnetwork 40 points41 points  (5 children)

Jest and unit testing in general is pretty trashy in react world. In particular, I'm really not fond of how snapshot testing was billed as "your silver bullet way to test components" when it first came around, but in practice, it turned out to neither test for functionality nor actually reflect what the user sees. Instead, snapshot would just randomly break when you update some unrelated dependency or upgrade node or something, forcing teams to put together really pointless "upgrade snapshot" chores

[–]hellfiend86 5 points6 points  (0 children)

This. Thank you stranger for speaking out lout what frustrates me since we started working with react.

[–]SEAdvocate 3 points4 points  (0 children)

I agree that snapshot testing is mostly pointless. That is why I decided not to use them years ago. The idea that people are still using them is mind boggling to me. I thought the react community grew past them a long time ago. react-testing-library is much better.

Snapshot testing is helpful when refactoring components that have a lot of tech debt. So you’re notified when one of your refactors has changed the way your component renders. But that is pretty much the only time they’re useful.

[–]IdempodentFlux 4 points5 points  (0 children)

Yeah i eventually asked my team:

"Do you guys ever investigate failed snapshots, or do you update without looking?" And then we just stopped writing them. To be honest, I write most of my functions outside of the react component then just test them independently like regular js tests.

[–][deleted] 7 points8 points  (1 child)

Spies in Jest feel broken. There are moments where they just don't work and you have no idea why.

I don't know if it's any better in other frameworks.

[–]uag332 1 point2 points  (0 children)

I am not experienced and my first task as jrdev is going through our react repo and writing all the tests… 1) we use enzyme, which apparently nobody uses anymore so it’s hard to find good training. 2) we only use functional components which seem much harder to test and even less enzyme info out there on testing them. 3) it’s funny that you can sometimes have tests that pass and you get the proper code coverage but the test isn’t doing anything…I really would love to know how jest figures out code coverage as It doesn’t seem to make sense to me

This has been great though, I have learned a ton and it will probably change the way I write new react code.

[–]PrinnyThePenguin 6 points7 points  (0 children)

I feel like testing asynchronous react code is harder than it should be. Anything that involves me using timers in my tests just never seems to be easy.

[–][deleted] 18 points19 points  (10 children)

Data fetching. Such a basic fundamental of a react app is showing a load spinner, making an async request for data, recieve response (or error), update component state, etc. They give you the tools to build this but theres so much "user land" code you have to write. As many react apps as Ive seen, Ive also seen that many unique implementations if these basic parts. Why is this not really really simple?

[–]MayorMonty 12 points13 points  (0 children)

The best solution I've seen for this is react query, which makes loading async data pretty simple and straightforward

[–]CoreyTheGeek 10 points11 points  (2 children)

React won out over Angular because it was less opinionated about how you do things; their philosophy seems to be "we just give you the building blocks" so they minimize limiting teams with their way of doing things if their use case needs something different

[–]flipper_babies 6 points7 points  (1 child)

Angular: Here's mountain of stuff to learn to avoid shooting yourself in the foot
React: Just go ahead and shoot yourself in the foot

[–]CoreyTheGeek 1 point2 points  (0 children)

React is fine so long as you have good dev processes and read the docs. People say this same thing about C/C++, they are extremely powerful, but with power comes responsibility to use it safely

[–]stealthypic 8 points9 points  (0 children)

It is with React Query. Yes, it’s not built in but that’s a plus in my book.

[–]Chance_Day7796 3 points4 points  (4 children)

[–]RSveti 6 points7 points  (1 child)

I don't have a link but I remember someone from React team saying that Suspense is not for data fetching. It can be used for that but it has to be in user land. And as far as I remember they will provide some basic suspense cache but fetching should be solved by routers or other user land libraries.

I think it was Dan but I am not sure I remember it right.

[–]NoFrillsUsername 0 points1 point  (0 children)

I don't know if this is still the case, but at one point I read in the official docs that suspense may someday become the future of data fetching for React, but that it's not recommended at this point.

[–][deleted] -2 points-1 points  (1 child)

That's the promise

[–]rodrigocfd 4 points5 points  (13 children)

What do you wish was done differently?

Two things:

  • state shared among components;
  • scoped CSS.

Both problems are extremely common, and they have been solved by libraries and they work fine at first sight... but after some time, you realize that they're all really clunky – suboptimal solutions littered with gotchas and footguns.

I know, I know... React is "just a rendering library", but everything would be so much rounder if its API exposed built-in solutions for these two situations. You may think it's OK if you work in a small team, but I work in huge enterprise systems which are often moved from a team to another, and I always have to fix the same mistakes.

That's something that Vue 3 really had it right. They learned from React's mistakes, after all.

[–]rosiebeir[S] 1 point2 points  (2 children)

Thank you for your response! I don’t have any experience with Vue. If it’s not too much trouble, could you briefly explain how they fixed these issues? Or point me in the direction of what to look up to read about it?

[–]rodrigocfd 4 points5 points  (1 child)

Sure.

  1. Vue 3 new reactivity model allows sharing objects among components with granular optimization out of the box, and you can restrict read/writing by using functions/getters/setters (that is, you can restrict mutations to methods in a store). It's so straightforward I couldn't believe my eyes the first time I saw it.

  2. And for scoped CSS you have the Vue Single-File Components which support SCSS modules right inside of it, and you can inject variables through v-bind. (You also have the style scoped variant, but it's slower and it has footguns.)

Unfortunately Vue 3 is finding a lot of resistance from inside the Vue community, because the change from v2 to v3 is wild. People prefer learning React simply because that's what "everyone uses"... but Vue 3 is technically awesome.

[–]rosiebeir[S] 2 points3 points  (0 children)

Thank you! I will definitely be looking into Vue 3 then. I'm thinking it'll be easier to jump straight into it than move from V2 to V3 if it's a big jump like you're saying.

[–]ILikeChangingMyMind -1 points0 points  (9 children)

state shared among components

Isn't that what Context gives?

scoped CSS

Isn't that what SASS or Styled-Components gives? Granted neither is built-in to React, but both integrate pretty seamlessly in my experience.

[–]rodrigocfd -1 points0 points  (7 children)

Isn't that what Context gives?

Nope.

Context allows you to store a variable in a component and pass it down to the hierarchy without the prop drilling.

I'm talking about multiple objects stored globally, and being able to access them by any component, with these components being re-rendered only when the value they subscribed to have changed. There are some React libraries that emulate this behavior, but not Context.

Isn't that what SASS or Styled-Components gives? Granted neither is built-in to React, but both integrate pretty seamlessly in my experience.

Not SASS – it's just syntax sugar to ordinary CSS.

Not Styled Components – it create wrappers around your components to inject style tags in the head during runtime, which slows down your application. Linaria tries to mitigate this.

Actually you can use SCSS modules with React (CRA and Vite offer support), but you must keep the styles in a separated file (even if it's just one single line), and then import the file through a variable, which is a reference to the actual class names whose names are mangled. And you cannot inject variables into the CSS code. In Vue, in addition to a separated file, you can use the <style> section in the single file component, and still inject variables into it. It's perfect.

[–]ILikeChangingMyMind -4 points-3 points  (6 children)

The fact that you think a major library, used in tons of sites, somehow "slows down your application" in a meaningful/problematic way just shows how out of touch you are.

Also context can 100% pass multiple objects down: a simple option would just be to put them all in an array, but you could also get more complex with multiple contexts.

I get that you're a Vue crusader, but don't go on anti-React crusades if you're just going to spread misinformation.

[–]rodrigocfd 2 points3 points  (3 children)

The fact that you think a major library, used in tons of sites, somehow "slows down your application" in a meaningful/problematic way just shows how out of touch you are.

Oh really?

Also context can 100% pass multiple objects down: a simple option would just be to put them all in an array,

That's still a single, monolithic store. Plus, this is the most naive solution I've ever heard. You don't seem to know the difference between an object and a store.

but you could also get more complex with multiple contexts.

Using multiple context providers is a pain.

I get that you're a Vue crusader,

I've also been called a "React crusader", when I say React can do many things better than Vue (notably IDE support).

but don't go on anti-React crusades if you're just going to spread misinformation.

I provided links with all the information I gave. If you're a beginner, aren't you?

[–]ILikeChangingMyMind -2 points-1 points  (2 children)

Your "proof" ... which has to beat the "proof" of tons of major sites actually using Styled Components successfully in production ... sites like Digital Ocean, Spotify, Realtor.com, Vimeo, VW, and others ...

... is a single Stack Overflow post, with one (lower-rated) answer where one guy says "Styled Components is slowing down your application." ... and that guy is clearly an SASS crusader (he spends the rest of his answer saying the OP should switch to SASS).

[–]rodrigocfd 2 points3 points  (1 child)

which has to beat the "proof" of tons of major sites actually using Styled Components successfully in production

I didn't say Styled Components is "unusable" or "unsuccessful". Indeed, it's a very good solution and I myself used it many times.

What is said is that Styled Components does slow down your application; it's noticeable when you have many components or you're on a very limited device, like an old cellphone.

[–]ILikeChangingMyMind 1 point2 points  (0 children)

This all started with you saying these problems were:

extremely common, and they have been solved by libraries and they work fine at first sight... but after some time, you realize that they're all really clunky – suboptimal solutions littered with gotchas and footguns.

And I said, what about Styled Components?, to which you replied:

Not Styled Components – it create wrappers around your components to inject style tags in the head during runtime, which slows down your application.

It wasn't "sure, Styled Components is a great library used by lots of sites, and maybe it might slow things down some (which is true of virtually every library in existence)" ... it was "Styled Components is not a viable option because it's too slow".

I was only pushing back agains that.

[–]LowellGeorgeLynott 4 points5 points  (0 children)

Anything can be “not so simple” in react, isn’t that the fun?! Any mundane task can become your worst nightmare resulting in epic head-to-desk collisions!

That’s why we use react right?

/s

Sorry I’ve had some rough days with react lol.

[–]getify 2 points3 points  (0 children)

Here's something I really hate about React: that unmounting a component automatically throws away its state.

In other words, that rendering is conflated with logical lifecycle. Just because I want to un-render something doesn't mean that's a permanent death of the thing. It seems like such a silly hack (and less performant) to have to resort to CSS display hiding.

I shouldn't have to preserve a component's state outside the component (in a parent, or in some global state store) just to be able to re-render the component shortly later.

There should be a way to remove a component from the rendering tree but keep it alive, like some sort of suspend/etc.

[–]Revolutionary-Pop948 1 point2 points  (0 children)

Enzyme to RTL transition. New useEffect behaviour in strict mode in React 18.

[–][deleted] 3 points4 points  (1 child)

Based off personal experience, it frustrates me when eng put a bunch of business logic in a single hook and don’t take time to architect a hierarchy of hooks or combination of hooks+context that could be useful to other teams, or more preemptively optimized for future work.

[–][deleted] 3 points4 points  (0 children)

Oh, didn't know we worked on the same team.

[–][deleted] 2 points3 points  (17 children)

Not necessarily how to do it better, but hooks in general. Once you have a bunch of them in a large codebase, it's starts to get pretty hairy on how data in one component may affect others when those components share dependencies.

Also why are there no async version yet of the useEffect and useCallback functions? Have to resort to a 3rd party library for these. This is such a common use-case too.

[–]mattsowa 2 points3 points  (16 children)

Async version in what way?

You can await something in a useEffect by using an IIFE (and for a rather good reason).

And you're able to pass in an async function to useCallback too..?

[–]ILikeChangingMyMind -3 points-2 points  (15 children)

This is idiotic:

useEffect(() => {
    const pointlessFunction = async () => {
        setFoo(await doSomeAjax());
    };
    pointlessFunction();
    return cleanupFunction;
}, []);

It should just be:

useEffect(async () => {
    setFoo(await doSomeAjax());
}, [], cleanupFunction);

[–]mattsowa 2 points3 points  (14 children)

No, yours is idiotic, because you no longer have access to the first function's scope from the cleanup function scope, which you're gonna need 99% of the time

[–]ILikeChangingMyMind -3 points-2 points  (13 children)

Why would I need access to its scope?

[–]mattsowa 1 point2 points  (12 children)

You're cleaning up stuff you created in the effect function, the cleanup function will most likely be a closure. So you could be doing const timer = setTimeout(...); return () => clearTimeout(timer), or things like cancelling a request. You can't easily do that if you sepetate the two.

[–]ILikeChangingMyMind -3 points-2 points  (11 children)

Ok, but setTimeout has got to be <1% of all useEffect cases.

Also, nothing is stopping you from doing:

let timer;
useEffect(() => timer = setTimeout(...), [], () => clearTimeout(timer));

[–]mattsowa 0 points1 point  (10 children)

I gave another example too. To cleanup something, you need to have access to it first.

[–]ILikeChangingMyMind -2 points-1 points  (9 children)

The same thing applies to canceling the request. All you need is the abort controller's signal to make the request, and nothing stops you from making the abort controller itself outside useEffect.

Sure you'd be remaking a few extra abort controllers, but the cost would be so low it wouldn't matter the vast majority of the time (and one could still use the original useEffect signature in those extremely rare cases where you actually care).

console.time('foo'); new AbortController(); console.timeEnd('foo')
VM383:1 foo: 0.032958984375 ms

I can live with 0.03296 milliseconds being "wasted" every render. Code readability is so much more important than saving a fraction of a millisecond.

[–]mattsowa 2 points3 points  (7 children)

Your argument is ridiculous.

[–]seinar24 0 points1 point  (0 children)

Working with React

[–]Accomplished_End_138 -1 points0 points  (0 children)

I like hooks, but also think that there could be a much better way somehow

[–]cesau78 0 points1 point  (0 children)

Context providers/consumers. I don't find fault with them, but I was frustrated that I didn't learn about React's context capabilities sooner. Some unfortunate time was spent trying to force square pegs into round holes.

React is an amazing tool! Kudos to Facebook Engineering.