Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Ape Fist
Feb 23, 2007

Nowadays, you can do anything that you want; anal, oral, fisting, but you need to be wearing gloves, condoms, protection.

prom candy posted:

You could put data-vars on the element that you're using for your React root and then load it as props when you mount the component:

code:
// Server-rendered template
<div id="react-root" data-my-var="@Model.MyASPVariable"></div>

// Mounting code
const rootNode = document.getElementById('react-root');
const props = rootNode.dataset
ReactDOM.render(<YourComponent {...props} />, rootNode);
Then in YourComponent everything you declared in the data tags will be available as props.

Seems like a good way of doing it too, yeah.

Adbot
ADBOT LOVES YOU

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

prom candy posted:

You could put data-vars on the element that you're using for your React root and then load it as props when you mount the component:

code:
// Server-rendered template
<div id="react-root" data-my-var="@Model.MyASPVariable"></div>

// Mounting code
const rootNode = document.getElementById('react-root');
const props = rootNode.dataset
ReactDOM.render(<YourComponent {...props} />, rootNode);
Then in YourComponent everything you declared in the data tags will be available as props.

I'd just make this one change:

code:
// Server-rendered template
<div id="react-root" data-my-Back-End-devs-are-little-stupid-loving-babies="@Model.MyASPVariable"></div>
// Mounting code
const rootNode = document.getElementById('react-root');
const props = rootNode.dataset
ReactDOM.render(<YourComponent {...props} />, rootNode);

Ape Fist
Feb 23, 2007

Nowadays, you can do anything that you want; anal, oral, fisting, but you need to be wearing gloves, condoms, protection.
What's the craic with React's control of DOM elements outside its container? Can I manipulate a DOM element not inside a React component the way we normally would with plain JS using a method inside a class or no? Sorry if this is very React 101 but I'm genuinely not involved with it at all.

prom candy
Dec 16, 2005

Only I may dance

Ape Fist posted:

What's the craic with React's control of DOM elements outside its container? Can I manipulate a DOM element not inside a React component the way we normally would with plain JS using a method inside a class or no? Sorry if this is very React 101 but I'm genuinely not involved with it at all.

Yup you can access document.whatever inside React. The older way would be using lifecycle methods (componentDidMount, componentDidUpdate, etc) inside a class, the newer way would be using the useEffect hook inside a Function Component. People do this to do stuff like add/remove classes from document.body or change document.title or measure the window size or whatever generic JS you can think of all the time. If you're still new to React I would go ahead and learn the useEffect way of doing it because despite being initially harder to understand it's better imo and people are slowly not using classes anymore anyway.

Ape Fist
Feb 23, 2007

Nowadays, you can do anything that you want; anal, oral, fisting, but you need to be wearing gloves, condoms, protection.
When does useEffect happen? After state had changed? Looks fairly straightforward.

prom candy
Dec 16, 2005

Only I may dance
useEffect happens on every render, but the second argument is an array of dependencies. It's kind of hard for me to explain from my phone, I think the docs are pretty good though.

https://reactjs.org/docs/hooks-effect.html

Also if you want to get really into it Dan Abramov wrote a whole lot about it here (worth reading if you think you're going to want to do a lot of React) https://overreacted.io/a-complete-guide-to-useeffect/

useEffect is probably the most complicated thing in React now but it's really powerful and after learning it I like it way more than the component lifecycle stuff.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

prom candy posted:

Also if you want to get really into it Dan Abramov wrote a whole lot about it here (worth reading if you think you're going to want to do a lot of React) https://overreacted.io/a-complete-guide-to-useeffect/


Dan Abramov's communication talents are one of the greatest strengths of React and Redux.

Chas McGill
Oct 29, 2010

loves Fat Philippe
Dan is a legend and a good guy.

I wish (this is in general rather than just about that useEffect article) that tutorial examples would show slightly more complex common use cases like making an async call that updates state when the component mounts etc. I don't think I've ever written a component that just increments a counter...

Social Animal
Nov 1, 2005

Are classes really being faded away? Like what usage scenarios would require a class over a function component?

ddiddles
Oct 21, 2008

Roses are red, violets are blue, I'm a schizophrenic and so am I
Right now I think the only thing a functional component with hooks cant replicate is the error boundary components, but they are planning on covering that as well.

tankadillo
Aug 15, 2006

Dan said in a Twitter thread that they might consider moving classes to a separate package in the future and vanilla react will just be functional.

Social Animal
Nov 1, 2005

What are the main disadvantages of classes? Does it add some kind of bloat? I'm asking as someone who always used classes and just wondering what the big deal about function components are.

dupersaurus
Aug 1, 2012

Futurism was an art movement where dudes were all 'CARS ARE COOL AND THE PAST IS FOR CHUMPS. LET'S DRAW SOME CARS.'

Social Animal posted:

What are the main disadvantages of classes? Does it add some kind of bloat? I'm asking as someone who always used classes and just wondering what the big deal about function components are.

Classes are too old. You can’t use anything older than five one year in modern js development.

prom candy
Dec 16, 2005

Only I may dance
The big problem with class components in React is that the lifecycle methods become difficult to follow. Unrelated code gets mixed up under the same componentDidMount or componentDidUpdate hooks, and if you have some logic that's spread across 2-3 different lifecycle methods it can be really hard to follow.

With hooks you can toss all related code in the same useEffect hook and if you've got a couple of different things going on in the same component that have effects you can just create a second useEffect hook to keep them separate (and because they'll probably have different dependencies).

The other big problem with classes is you can't use hooks in them (default or custom) and pretty soon there's gonna be a lot of great libraries that don't export anything but hooks.

But yeah it's also a newness thing, everyone in React world is down on OOP and rock hard for FP lately so classes are now uncool.

Social Animal
Nov 1, 2005

prom candy posted:

The big problem with class components in React is that the lifecycle methods become difficult to follow. Unrelated code gets mixed up under the same componentDidMount or componentDidUpdate hooks, and if you have some logic that's spread across 2-3 different lifecycle methods it can be really hard to follow.

With hooks you can toss all related code in the same useEffect hook and if you've got a couple of different things going on in the same component that have effects you can just create a second useEffect hook to keep them separate (and because they'll probably have different dependencies).

The other big problem with classes is you can't use hooks in them (default or custom) and pretty soon there's gonna be a lot of great libraries that don't export anything but hooks.

But yeah it's also a newness thing, everyone in React world is down on OOP and rock hard for FP lately so classes are now uncool.

I like OOP though :( This is pretty interesting but I'll admit I haven't kept up with this hooks stuff. Will need to dive in and check it out to see what's going on.

dupersaurus
Aug 1, 2012

Futurism was an art movement where dudes were all 'CARS ARE COOL AND THE PAST IS FOR CHUMPS. LET'S DRAW SOME CARS.'
Snark aside, with what little I've read about hooks so far, they do sound like the logical end point of The React Way. It also mirrors some patterns appearing in other domains, like entity component system in game dev, which has similar issues with widely-shared functionality sharing that doesn't easily fit into parent-child boxes.

Ape Fist
Feb 23, 2007

Nowadays, you can do anything that you want; anal, oral, fisting, but you need to be wearing gloves, condoms, protection.
yeah haskell is cool a guess

prom candy
Dec 16, 2005

Only I may dance

Social Animal posted:

I like OOP though :( This is pretty interesting but I'll admit I haven't kept up with this hooks stuff. Will need to dive in and check it out to see what's going on.

Hooks are so incredibly good and useful, don't ignore them. I've written a ton of custom hooks both big and small since their release and it's made it so much easier to share logic between largely unrelated components. It also makes the DX for stuff like using refs and context way, way nicer.

OOP is fine but it's not like React ever really embraced it anyway. You can't really set up inheritance chains, you can't use mixins, etc. JavaScript is not a classically OOP language, the class stuff is just syntactic sugar and I think most people are using it to keep code scoped and organized rather than do a lot of real OOP. There's prototypical inheritance but I've given up on ever understanding how that works.

Ruggan
Feb 20, 2007
WHAT THAT SMELL LIKE?!


prom candy posted:

Hooks are so incredibly good and useful, don't ignore them. I've written a ton of custom hooks both big and small since their release and it's made it so much easier to share logic between largely unrelated components. It also makes the DX for stuff like using refs and context way, way nicer.

Can you give an example of a custom hook you’ve written outside a component and shared across multiple?

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



Social Animal posted:

I like OOP though :( This is pretty interesting but I'll admit I haven't kept up with this hooks stuff. Will need to dive in and check it out to see what's going on.

prom candy mentioned this, and I'm not sure how well you know the language, but JS probably doesn't have OOP like you think it does. It has a prototype chain instead of member inheritance. The class syntax is just sugar for that, not a different inheritance paradigm.

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

Ruggan posted:

Can you give an example of a custom hook you’ve written outside a component and shared across multiple?

I'm not Ruggan, but in the app I'm working on I've written general-purpose hooks to handle form input and validation, keep track of page / element resize that updates component state with the new container size, etc.

prom candy
Dec 16, 2005

Only I may dance

Ruggan posted:

Can you give an example of a custom hook you’ve written outside a component and shared across multiple?

One I wrote pretty early on was useSelectable, which I use for pages where users need to be able to select a bunch of items to perform actions on.

code:
const ids = someOfMyData.map(data => data.id);
const { selectedIds, selectNone, selectAll, selectOnly, toggleSelected } = useSelectable(ids);
So now whenever I have a page that needs selection I can just pull that in. I also set it up to use context so I can provide the ids at the top level and then do selection stuff lower (e.g. check if a single row is selected inside that row component) without having to do a bunch of prop drilling.

Another one I wrote is called useFilterManager, which tracks which filters have been applied to a list, allows the user to change filters, returns an up-to-date version of the filter state (for keeping the UI responsive) as well as a debounced version (so that a user can check few boxes or type something without firing off a ton of fetch requests in a row.)

These are just things I needed because we deal with big lists of data that need to be filtered, selected, and operated on. Your own app might have different needs. Sometimes they're more specific too. For example in another app I have 3 places where a user needs to be able to manage their Getty Images account (either connect with Getty Images if they aren't, or disconnect if they are) and all 3 places need to look completely different from each other. So I made a useGettyAccount hook that pulls the current user out of Redux state, handles all that logic, and then returns something like { isConnected, connectGetty, disconnectGetty, isConnecting, isDisconnecting }.

tankadillo
Aug 15, 2006

Ruggan posted:

Can you give an example of a custom hook you’ve written outside a component and shared across multiple?

There are a few I’ve used or seen in the wild.

Gets or sets a value to a local storage key:
code:
[value, setValue] = useLocalStorage("key", "default value”);
Takes an array of objects and sorts them according to a specified object key. The dispatch is a reducer that can change the sort order or the table contents. Useful for an app that’s heavy on tabular data:
code:
[{table, isDescending, sortKey}, dispatch] = useSortedTable(arrayOfData);
This is pretty simple, it’s just a wrapper for useEffect that changes document.body.style.cursor based on whether or not data is loading.
code:
useLoadingCursor(isLoaded);
Something I saw recently is that you can use the output of one hook as the input for another hook.

Log whatever the state is:
code:
[value, setValue] = useLogger(useState("something to log"));
Keep a history of each state change, and return functions to undo/redo it:
code:
[value, setValue, undo, redo] = useUndo(useState("something"));
The last two are taken from here https://github.com/mjackson/react-loop-2019/blob/master/hooks.js

Social Animal
Nov 1, 2005

So I finally read the docs and yeah hooks seem pretty cool. Looking back at my last job I could definitely think of where I would have loved to implement some custom hooks. Although deep down I was hoping it included a substitute for redux. My last project before leaving was a jquery to react rewrite utilizing separate pages so no global state was needed on the frontend. It felt so good to not have to deal with it.

prom candy
Dec 16, 2005

Only I may dance

Social Animal posted:

So I finally read the docs and yeah hooks seem pretty cool. Looking back at my last job I could definitely think of where I would have loved to implement some custom hooks. Although deep down I was hoping it included a substitute for redux. My last project before leaving was a jquery to react rewrite utilizing separate pages so no global state was needed on the frontend. It felt so good to not have to deal with it.

Having a much more developer-friendly context API eliminates the need for Redux in a lot of cases.

tankadillo
Aug 15, 2006

useContext + useReducer is a really painless way to handle global state now.

prom candy
Dec 16, 2005

Only I may dance
Don't put all your state in the same context though because every component that subscribes to a given context will re-render when any of that context changes. Right now there's no way to subscribe to just a slice of larger context or bail out of renders from context changes. As usual Kent C. Dodds has a great article on this: https://kentcdodds.com/blog/how-to-use-react-context-effectively

I just wrote a little custom hook now that might be a simpler example: when the component mounts, add a className to the body tag. If the className passed in changes, remove the old className and add the new one. If the component unmounts, remove the className:

code:
import { useEffect, useRef } from 'react';

export default function useBodyClassName(className: string) {
  const prevClassName = useRef(className);

  useEffect(
    () => {
      document.body.classList.remove(prevClassName.current);
      document.body.classList.add(className);
      prevClassName.current = className;
      return () => {
        document.body.classList.remove(className);
      };
    },
    [className]
  );
}
Here's the test case:

code:
import React from 'react';
import useBodyClassName from './useBodyClassName';
import { render, flushEffects } from 'react-testing-library';

interface TestCaseProps {
  className: string;
}

function TestCase({ className }: TestCaseProps) {
  useBodyClassName(className);
  return null;
}

it('manages the document body className', () => {
  // Render with initial props
  const { container, unmount } = render(<TestCase className="foo" />);
  flushEffects();
  expect(document.body).toHaveClass('foo');

  // Re-render with a different className
  render(<TestCase className="bar" />, { container });
  flushEffects();
  expect(document.body).not.toHaveClass('foo');
  expect(document.body).toHaveClass('bar');

  // Unmount and clear the classNames
  unmount();
  flushEffects();
  expect(document.body).not.toHaveClass('foo');
  expect(document.body).not.toHaveClass('bar');
});

putin is a cunt
Apr 5, 2007

BOY DO I SURE ENJOY TRASH. THERE'S NOTHING MORE I LOVE THAN TO SIT DOWN IN FRONT OF THE BIG SCREEN AND EAT A BIIIIG STEAMY BOWL OF SHIT. WARNER BROS CAN COME OVER TO MY HOUSE AND ASSFUCK MY MOM WHILE I WATCH AND I WOULD CERTIFY IT FRESH, NO QUESTION

Ape Fist posted:

We do front end in a very bad way and our back end devs are annoyed

No poo poo

gbut
Mar 28, 2008

😤I put the UN🇺🇳 in 🎊FUN🎉


https://twitter.com/markdalgleish/status/1144223814256979968?s=19

prom candy
Dec 16, 2005

Only I may dance
My build step on my React app is really slow. I've also been working on splitting things out with lazy loading and I've been a bit confused about why things end up in certain chunks. I started digging on the create-react-app GitHub issues and I found this comment claiming that doing and import like

code:
import { ComponentA } from 'components'
causes webpack to have to look at your whole components index file and then treeshake down the whole thing. I have a MASSIVE shared components index (115 components) and I import from it all over the drat place in various ways, stuff like

code:
import { Modal, Form, Button } from 'components'
So I have two questions:

1. does anyone know if what that commenter is saying is true? I import from that components index in 340 separate places in my app so if webpack is having to do extra calculation on the entire index file every single time no wonder it's so drat slow

2. If that is the case does anyone know how I could find every instance of that kind of import in my code and automatically convert it to

code:
import Modal from 'components/Modal';
import Form from 'components/Form';
import Button from 'components/Button';
I guess I'll probably need a bash script?

Edit: found this, it'll probably do the trick https://github.com/suchipi/transform-imports

prom candy fucked around with this message at 14:52 on Jun 30, 2019

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

prom candy posted:


Edit: found this, it'll probably do the trick https://github.com/suchipi/transform-imports

Let us know if it speeds stuff up!

Ape Fist
Feb 23, 2007

Nowadays, you can do anything that you want; anal, oral, fisting, but you need to be wearing gloves, condoms, protection.

Just use jquery and vanilla CSS forever what's the problem. I can understand their frustration to a degree because front end changes dramatically with every senior fed they bring into the company but its not really my fault that ASP.NET 4.6 + Episerver CMS are as hostile to modern FED as they are.

Ape Fist fucked around with this message at 17:08 on Jun 30, 2019

prom candy
Dec 16, 2005

Only I may dance

Thermopyle posted:

Let us know if it speeds stuff up!

Hmm, so I split everything up and the results are not what I expected.

Before
First build: 55.20s
Subsequent build: 50.57s

Total size of build folder: 17M (incl. source maps)
Total chunks created: 17

After
First build: 116.41s
Subsequent build: 61.69s

Total size of build folder: 21M (incl. source maps)
Total chunks created: 23

So it looks like the build is actually slower, and it results in a larger overall build, but obviously importing from an index is causing quite a few things to get chunked together that probably shouldn't be. In both cases I wind up with one chunk file that's sized at over 600KB after gzip which imo is still too drat big for a single chunk so at this point I'm not really sure if I should get rid of indices and always do direct file imports so I can hunt down my bad chunks or if I should stick with the indices or if there's something else I can do to improve build times. I guess ~1m isn't terrible but faster would be nice.

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

prom candy posted:

Hmm, so I split everything up and the results are not what I expected.

Before
First build: 55.20s
Subsequent build: 50.57s

Total size of build folder: 17M (incl. source maps)
Total chunks created: 17

After
First build: 116.41s
Subsequent build: 61.69s

Total size of build folder: 21M (incl. source maps)
Total chunks created: 23

So it looks like the build is actually slower, and it results in a larger overall build, but obviously importing from an index is causing quite a few things to get chunked together that probably shouldn't be. In both cases I wind up with one chunk file that's sized at over 600KB after gzip which imo is still too drat big for a single chunk so at this point I'm not really sure if I should get rid of indices and always do direct file imports so I can hunt down my bad chunks or if I should stick with the indices or if there's something else I can do to improve build times. I guess ~1m isn't terrible but faster would be nice.

What's it look like without source maps, as that's the important bit.

prom candy
Dec 16, 2005

Only I may dance

Lumpy posted:

What's it look like without source maps, as that's the important bit.

Before: 4.2M
After: 5.1M

I don't even understand where an extra ~900KB would be coming from. I guess code must be getting duplicated into multiple chunks.

putin is a cunt
Apr 5, 2007

BOY DO I SURE ENJOY TRASH. THERE'S NOTHING MORE I LOVE THAN TO SIT DOWN IN FRONT OF THE BIG SCREEN AND EAT A BIIIIG STEAMY BOWL OF SHIT. WARNER BROS CAN COME OVER TO MY HOUSE AND ASSFUCK MY MOM WHILE I WATCH AND I WOULD CERTIFY IT FRESH, NO QUESTION

Ape Fist posted:

Just use jquery and vanilla CSS forever what's the problem. I can understand their frustration to a degree because front end changes dramatically with every senior fed they bring into the company but its not really my fault that ASP.NET 4.6 + Episerver CMS are as hostile to modern FED as they are.

It's not your fault, but it's your responsibility as the lead front end developer, I would have thought. Of course they're annoyed that the front end stuff is a mess, it's not a blame thing, it's a "hey you're in charge of this now can you do something about it" thing. If you're not actually empowered in your position to make any meaningful changes as a front end lead then you should probably head somewhere else for your own sanity, because people will always complain about stuff that makes their day-to-day lovely.

reversefungi
Nov 27, 2003

Master of the high hat!
Do y'all prefer function expressions or function statements for React functional components? The Hooks documentation uses statements, so it seems like that might be better, but I'm wondering if there are solid arguments for the other direction.

E.g.
JavaScript code:
const App = () => {} // expression

//vs

function App() {} // statement

Doom Mathematic
Sep 2, 2008

The Dark Wind posted:

Do y'all prefer function expressions or function statements for React functional components? The Hooks documentation uses statements, so it seems like that might be better, but I'm wondering if there are solid arguments for the other direction.

E.g.
JavaScript code:
const App = () => {} // expression

//vs

function App() {} // statement

I generally prefer arrow functions to regular function expressions in every situation where an arrow function will do the job (which is admittedly not everywhere), and I prefer function expressions (const App = function () {}) to function statements (function App() {}) everywhere else. Regular functions defined using function have this as an invisible/implicit named argument, which is something I prefer to keep to an absolute minimum. They also allow you to mess with arguments, which (though people don't do it too often) confounds my ability to search for uses of individual named arguments. And they get hoisted, allowing you to write const app = App(); function App() {}, which I mildly dislike. And they're just plain more verbose.

These are mostly just preferences though.

Doom Mathematic fucked around with this message at 23:33 on Jul 2, 2019

dupersaurus
Aug 1, 2012

Futurism was an art movement where dudes were all 'CARS ARE COOL AND THE PAST IS FOR CHUMPS. LET'S DRAW SOME CARS.'

Doom Mathematic posted:

I generally prefer arrow functions to regular function expressions in every situation where an arrow function will do the job (which is admittedly not everywhere), and I prefer function expressions (const App = function () {}) to function statements (function App() {}) everywhere else. Regular functions defined using function have this as an invisible/implicit named argument, which is something I prefer to keep to an absolute minimum. They also allow you to mess with arguments, which (though people don't do it too often) confounds my ability to search for uses of individual named arguments. And they get hoisted, allowing you to write const app = App(); function App() {}, which I mildly dislike. And they're just plain more verbose.

These are mostly just preferences though.

What’s the diff between arrow and expression?

Adbot
ADBOT LOVES YOU

prom candy
Dec 16, 2005

Only I may dance
I use statements because it's easier to do

export default function Whatever() {}

than

const Whatever = () => {}

export default Whatever

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply