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
Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense

Obfuscation posted:

Now all you need is a state management system that knows which templates to re-render when your state changes and whoops, you have re-invented react

That's the big feature for sure. But sometimes I prefer to just

JavaScript code:
function updateCat (props) {
    const cat = cats.find(({ id }) => id === props.id);
    if (cat) {
        cat.elements.name.innerHTML = props.name;
    }
}
Or whatever.


In a lot of cases I don't need everything to react to events.

Nolgthorn fucked around with this message at 15:04 on Jan 31, 2023

Adbot
ADBOT LOVES YOU

go play outside Skyler
Nov 7, 2005


roomforthetuna posted:

Man, if they'd made react *without* the state management system then there might be a framework that I don't hate and wish death upon.

but that's just JSX, which was my point: it should be part of javascript, and i shouldn't need webpack to use it

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
Does this count as jsx? Could do a full json version of it would be easier to read.

JavaScript code:
function ele (name, attrs, ...children) {
    const element = document.createElement(name);
    for (const [key, value] of Object.entries(attributes)) {
        element.setAttribute(key, value);
    }
    for (const child of children) {
        if (typeof child === 'string') {
            element.appendChild(document.createTextNode(child));
        } else {
            element.appendChild(child);
        }
    }
    return element;
}

ele('div', { class: 'cat' },
    ele('div', { class: 'name' }, 'I\'m a cat'),
    ele('div', { class: 'avatar' },
        ele('img', { src: 'https://blahblah' })
    )
);

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

Nolgthorn posted:

Does this count as jsx? Could do a full json version of it would be easier to read.

JavaScript code:
function ele (name, attrs, ...children) {
    const element = document.createElement(name);
    for (const [key, value] of Object.entries(attributes)) {
        element.setAttribute(key, value);
    }
    for (const child of children) {
        if (typeof child === 'string') {
            element.appendChild(document.createTextNode(child));
        } else {
            element.appendChild(child);
        }
    }
    return element;
}

ele('div', { class: 'cat' },
    ele('div', { class: 'name' }, 'I\'m a cat'),
    ele('div', { class: 'avatar' },
        ele('img', { src: 'https://blahblah' })
    )
);

JSX is when you write a transpiler that turns this:

code:
<div className="cat">
  <div className="name">I'm a cat</div>
  <div className="avatar"><img src="https://blahblah" /></div>
</div>
into exactly the code you wrote.

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
Simplest solution is just

JavaScript code:
const html = `
  <div class="cat">
    <div class="name">${name}</div>
    <div class="avatar"><img src="${src}" /></div>
  </div>
`;
What would be close enough to jsx ?

Semisomnum
Aug 22, 2006

Half Asleep


It sounds like you guys are just describing Web Components. Its pretty much react components without the reactive variable stuff.

https://developer.mozilla.org/en-US/docs/Web/Web_Components

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
^ Yes that's the thing I was wondering what happened to it but couldn't remember what they were called.


The following

JavaScript code:
const element = document.createRange().createContextualFragment(html);
wherever.appendChild(element);
Continuing my previous post this seems to be the most up to date way to work with dom nodes from an html string using vanilla javascript. You can perform all the expected operations like `element.querySelector` and etc. It's more up to date than `DOMParser` apparently.

marshalljim
Mar 6, 2013

yospos
Is Web Components even alive? I ran into one project that was delivered that way a while back (some kind of a videogame thing the details of which I have forgotten). Doesn't seem to be common/popular at all, though...

necrotic
Aug 2, 2005
I owe my brother big time for this!
Ionic has a lot of Web Components in recent versions, and we’ve started seeing more custom usage of them in our customer base.

Semisomnum
Aug 22, 2006

Half Asleep


The MDN page I linked has a few projects at the bottom that have recent commits. Lit looks like its just React/Vue but WC-based.

I imagine most people don't bother with them since React, Vue, etc. are basically the same thing but easier, with a much larger ecosystem of tutorials and libraries. Plus a great deal more hype.

Roadie
Jun 30, 2013
Web components suck in a bunch of ways, the most obvious being that your only input method for them is strings and so for anything even mildly complex you end up with a lot of time and effort spent on just stringifying, unstringifying, and verifying attributes.

One of the basic reasons that JSX exists is that it's syntactically 'just Javascript' where the transformation into actual HTML only happens in the output of whatever renderer you're using.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Roadie posted:

Web components suck in a bunch of ways, the most obvious being that your only input method for them is strings and so for anything even mildly complex you end up with a lot of time and effort spent on just stringifying, unstringifying, and verifying attributes.
Fuuuuck, that's what was wrong with ... whatever the loving framework was that I used briefly at Google before rewriting the thing in vanilla javascript to get away from it.

I mean not the only problem, the reactive attribute-parsing was the worst, trying to debug-step through what was happening when each automatic attribute set/get turned into a thing four function calls deep, and potentially triggered more attribute-changes, each of which made another four function calls deep, so the stack would get absolutely giant with unreadable bullshit, but each of those attribute things involving stringification and back was a big part of *why* it was layers and layers of unreadable shite functions.

The conversion to vanilla js actually reduced the number of lines of code in the app itself, so you know the framework was good.

camoseven
Dec 30, 2005

RODOLPHONE RINGIN'
I hate web components so much. It's possible there's a good way to use them, but every implementation I've been forced to work with has been an absolute mess

MrMoo
Sep 14, 2000

Web Components are accelerated by the browser, and thus enable 10,000's of dynamic elements on a page, which can be useful.

Dumb question of the day, is it actually possible to execute a ES6M app in NodeJS yet? I just started noticing errors that I should be using ".mts" extensions.

fuf
Sep 12, 2004

haha
This is a pretty vague question but for a basic React app without too much data is one of these two data models obviously better than the other?

option 1:
code:
class Category
   id: number
   name: string
   tags: Tag[]

class Tag
   id: number
   name: string
option 2:
code:
class Category
   id: number
   name: string

class Tag
   id: number
   name: string
   categoryId: number
option 3: ??

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

fuf posted:

This is a pretty vague question but for a basic React app without too much data is one of these two data models obviously better than the other?
Depends on how you use the data. If you look up tags by category then the latter is bad. If you look up categories by tag, or tags are frequently reused, then the former may be bad because you're duplicating the tags rather than reusing them, unless they're in a lookup table and you're doing an array of references. If you're trying to be flexible like how you would design a SQL database for the same data and allowing lookups in both directions then you want neither of them to contain the other, then instead you'd have a map of categories indexed by id, a map of tags indexed by id, and a map{categoryId:tagReferences} and/or map{tagId:categoryReferences} so you can do quick lookups in either direction.

But you could also do it without map-lookups at all if you make each category contain its set of tagReferences and each tag contain its set of categoryReferences. If you do it that way *and* you want to serialize the data then you have to serialize the two lists without their references, and serialize the reference data separately.

Sad Panda
Sep 22, 2004

I'm a Sad Panda.
I decided that it was time to learn JavaScript. I grabbed WebStorm as an IDE (teacher so educational licence for free) and have bought a course on Udemy (https://www.udemy.com/course/the-complete-javascript-course/). I've hobby coded in Python for a while so just going through the fundamentals now and they're going to be rather similar I'm sure.

The video was just about template literals and they remind me of f-strings in Python which are so lovely. In the video they mention that some people just use `` for every string moving forward. A quick search seemed to find some arguing that it's a bad idea (performance makes it slower as a blank template string literal needs parsing whereas a string in quote marks doesn't?) but just curious for best practice? I might end up moving towards using JS for a job so would rather avoid bad practice.

teen phone cutie
Jun 18, 2012

last year i rewrote something awful from scratch because i hate myself

Sad Panda posted:

I decided that it was time to learn JavaScript. I grabbed WebStorm as an IDE (teacher so educational licence for free) and have bought a course on Udemy (https://www.udemy.com/course/the-complete-javascript-course/). I've hobby coded in Python for a while so just going through the fundamentals now and they're going to be rather similar I'm sure.

The video was just about template literals and they remind me of f-strings in Python which are so lovely. In the video they mention that some people just use `` for every string moving forward. A quick search seemed to find some arguing that it's a bad idea (performance makes it slower as a blank template string literal needs parsing whereas a string in quote marks doesn't?) but just curious for best practice? I might end up moving towards using JS for a job so would rather avoid bad practice.

typically any company would have a linter and formatter, so more often-than-not, you'll have your quotes converted to either single or double quotes when formatting.

i think eslint (popular linter) and prettier (popular formatter) comes out of the box with rules for double quotes, so i'd go with that unless you need the backticks to add variables

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense

fuf posted:

option 3: ??
code:
class Category
   id: number
   name: string

class Tag
   id: number
   name: string

class CategoryTag
  categoryId: number
  tagId: number
To me this doesn't seem like a good solution because you're still performing operations that are as expensive as they would be if you stuck a categoryId onto each Tag. If you don't need a many to many relationship and you don't need additional parameters on CategoryTag then go with the simpler option.

You are probably more often finding tag references from the category so I'd reference tags within the category.

Nolgthorn fucked around with this message at 23:03 on Feb 8, 2023

Sad Panda
Sep 22, 2004

I'm a Sad Panda.

teen phone cutie posted:

typically any company would have a linter and formatter, so more often-than-not, you'll have your quotes converted to either single or double quotes when formatting.

i think eslint (popular linter) and prettier (popular formatter) comes out of the box with rules for double quotes, so i'd go with that unless you need the backticks to add variables

Thanks, got prettier & eslint installed and leaving with the default options. As you said, if I get a job then whoever I'm working for will explain their prettier settings to me - that makes sense.



Next JavaScript silly question... my previous JS experience was when I was writing a lot of Python in Selenium to scrape webpages. When doing this I got really tired of finding the elements so I wrote myself plenty of helper methods and frequently saved the element as a variable and referred to it that way. Is this seen as poor practice?

JavaScript code:
// that first part got really tedious when I keep manipulating the same element
document.querySelector('.score').textContent = '5';

// so something like this instead
const scoreEle = document.querySelector('.score');
scoreEle.textContent = '5';

teen phone cutie
Jun 18, 2012

last year i rewrote something awful from scratch because i hate myself

Sad Panda posted:

Next JavaScript silly question... my previous JS experience was when I was writing a lot of Python in Selenium to scrape webpages. When doing this I got really tired of finding the elements so I wrote myself plenty of helper methods and frequently saved the element as a variable and referred to it that way. Is this seen as poor practice?

JavaScript code:
// that first part got really tedious when I keep manipulating the same element
document.querySelector('.score').textContent = '5';

// so something like this instead
const scoreEle = document.querySelector('.score');
scoreEle.textContent = '5';

nope that's just good coding. don't repeat yourself as much as you can get away with

AlphaKeny1
Feb 17, 2006

I'm also glad you used const instead of let to assign the DOM node to a variable

edit: correct me if I'm wrong but I think your first example is a holdover from jquery where you'd have to query the selector each and every time you want to do something? Don't use jquery.

AlphaKeny1 fucked around with this message at 20:21 on Feb 17, 2023

Sad Panda
Sep 22, 2004

I'm a Sad Panda.

AlphaKeny1 posted:

I'm also glad you used const instead of let to assign the DOM node to a variable

edit: correct me if I'm wrong but I think your first example is a holdover from jquery where you'd have to query the selector each and every time you want to do something? Don't use jquery.

Thanks for that feedback. Given it a bit of a read after your comment, seems to suggest using document.getElementByID() and siblings unless complex in which case maybe querySelector(). Seem reasonable?

edit -- question...

JavaScript code:
function doStuff({ team1 = "Man U", team2 = "Chelsea", score }) {
  console.log(`${team1} played ${team2}. The score was ${score}`);
}
My understanding of this is that an object is passed in to the doStuff function, and then it destructured so it explicitly has access to team1, team2 and score (assuming they were properties of that object and if not they'll exist as undefined). If I wanted to later access the object itself, what's the best way to do that? Playing around in Webstorm I can see it exists in arguments[0]. Is there anywhere else? Mainly out of curiosity than thinking it is good practice.

Sad Panda fucked around with this message at 19:21 on Feb 21, 2023

Roadie
Jun 30, 2013

Sad Panda posted:

If I wanted to later access the object itself, what's the best way to do that?

Don't destructure the first argument.

Kwolok
Jan 4, 2022
I am working on a spa at a new company. They are using the new Google Identity Services. I sort of understand it but am confused on some key points:

So my understanding is that I implement google's client side script on my SPA, and then it logs into google and returns a jwt from google. Now this is the part that I get kind of muddied on. I know jwt's shouldn't be stored in local storage, and that ideally they should be stored in an httponly cookie, but it doesn't seem like the response from GIS stores them that way (and I believe a cookie can only be set by the sender). I am trying to figure out how to "remember" that hte user has authetnicated through GIS so that they don't have to do it on every refresh of the page.

I don't have the ability to let the backend act as a middleman in the request either, so I cannot have the backend set it as a cookie either. I am supposed to get my JWT from google, and then use that as the Bearer for subsequent requests for the backend. But I am having a hard time wrapping my head around this...

necrotic
Aug 2, 2005
I owe my brother big time for this!
If you don’t have a middleman API layer to handle an HttpOnly cookie I think your kind of stuck using local storage if you want it to persist across hard refreshes / a later session.

fuf
Sep 12, 2004

haha
I have another really basic React question: where's a good place to put my functions? Like the actual nuts and bolts of what the app is doing beyond just state management and interface components.

Like assume I have my "tags" state stored in a Context, and then I have individual components for AddTag, ListTags, etc.

Where do I put my "addTag", "deleteTag" etc. functions?

If it was MVC then these would all be in a separate controller, but it doesn't look like React really talks about controllers? I want to put them in a separate file but I don't know what kind of file it should be (a library??) or how to reference it.

I know I could put the "addTag" logic directly in the AddTag component, but there are also other places in the app where tags are created, so I'd have to duplicate the logic which seems bad.


I'm using React contexts rather than zustand, but as an example if you look at something like the zustand "quick start" documentation then they have:
code:
const useBearStore = create((set) => ({
  bears: 0,
  increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
  removeAllBears: () => set({ bears: 0 }),
}))
Which is fine, but presumably in a real app stuff like "increasePopulation" is going to have a whole lot of extra logic attached and you'd want to separate it out into another file somehow?

smackfu
Jun 7, 2004

If you want to reuse a function, just put it in a separate file, export it in that file, then import it where you want to use it. Not really more complicated than that.

fuf
Sep 12, 2004

haha
Ok, sorry for the dumb questions but how do I reference the app state in those external files?

Like right now in my AddTag component I can do:
code:
const tags = useContext(AppContext).tags;
const setTags = useContext(AppContext).setTags;
and then make use of these in a function within that component to add new tags.

But if I want to move that function into its own file I can't use useContext anymore...

smackfu
Jun 7, 2004

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

fuf
Sep 12, 2004

haha

Oh yeah that's exactly what I want, thank you.

This is exactly like my question about (what turned out to be) "prop drilling" a few pages ago: I've seen custom hooks mentioned a lot but couldn't see why they were useful until now.

I'm really reinventing React from first principles over here.

E: So does something like this make sense?

JavaScript code:
// useAddCategory.js

const { AppContext } = require("AppContextProvider");
const { useContext } = require("react");

export default function useAddCategory() {
  const setCategories = useContext(AppContext).setCategories;

  const addCategory = (title) => {
    const newCategory = new Category(title);
    setCategories((categories) => {
      return [newCategory, ...categories];
    });
  };
  return addCategory;
}

// AddCategory.js
export default function AddCategory() {

    const addCategory = useAddCategory();

    const handleKeyPress = (event) => {
        if (event.key === 'Enter') {
            addCategory(title);
        }
    }
At first I tried to just call useAddCategory directly, but I think the custom hook needs to return something (in this case a function) that gets used at the top level of the component rather than within a nested function.

I don't really understand how rendering etc. works but is this, like, creating a new version of the addCategory function every time the component renders? Does that matter?


fuf fucked around with this message at 15:57 on Feb 23, 2023

minato
Jun 7, 2004

cutty cain't hang, say 7-up.
Taco Defender
For larger apps, "where to store state" in React has always puzzled me. Many React tutorials assume that your state is kept in the components itself. But I don't know what to do when state needs to be shared, or when business logic outgrows cohabiting with React.

Like, say I'm making a Trello "ToDo list" SPA. My initial load pulls in the lightweight list of ToDo items, and my ToDo_Item data object looks like:
- Title: Do the needful
- Status: In Progress
- Details: [empty on first load, because it's too heavyweight for the List view]

Then the user clicks an item to pop open the Detail view, the app fetches the details from the server to populate the ToDo_Item object, and displays the <ItemDetail> component. The user updates the Status and returns to the <ListItems> view. So when this <ListItems> view re-renders, where is it fetching the updated item's Status from? The Status needs to be shared in both the <ListItems> and <ItemDetail> components.

It seems there's a few schools of thought:

1) Intermingle the state with React. The ToDo_Item object is stored in a React <Context> that contains both the <ListItems> & <ItemDetail> "pages", and so its data is accessible to both. This is simple, but intermingling React code and business logic smells bad when the amount of business logic gets big.



2) Separate the data from the rendering.

The ToDo_Item object is stored outside the React app, and knows nothing of React. It has an internal API for updating it and pubsub for interested observers. The React side of the app is one of those internal API users. When React wants to show a <ListItems> or <ItemDetail> views, it creates those and subscribes them to the internal API to access the object's state. This seems architecturally elegant because it separates concerns well, but it's also feels very heavyweight. (I want to support the server pushing Status updates made by other users, so it feels right to me to have a separate part of the app receive and re-publish those events to React.)



This strongly suggests that the "React UI renderer" system would maintain a copy of the items in the "TODO Item Manager". Which seems architecturally pure, but also now we're duplicating data and possibly data structures across the 2 internal systems. This feels too heavyweight.


I don't really like either solution. One is too simple, the other is too complex. It feels like there should be some middle ground, where I can elegantly separate my data objects from my display code, but not be burdened with creating complex systems for them to talk to each other. I'd love to know how others solve this, but all the apps I've seen are either too trivial or insanely complex.

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice
Keep data / state as close to where it is used as possible

Ex: If I have an app with four sections and one of them is TODOs, and the other three sections don't do anything with ToDos, then only the top-level TODO component knows anything about them, and I keep that state there. Or lower if possible! My app does have authentication though, so all my sections need to know about the User object (just as an example, they may not!) So I will probably create a UserContext, and expose a hook called useUserData or something like that so any component in the app can get that.

EDIT: and you can make your "TODO Knowing Code" a hook as well and just expose the bits you want to your top-level TODO component.

Lumpy fucked around with this message at 21:00 on Feb 23, 2023

barkbell
Apr 14, 2006

woof
just use tanstack query

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Kwolok posted:

I am working on a spa at a new company. They are using the new Google Identity Services.
Related question - is there a library that makes Oauth/OpenID just for login easy for the developer and user-friendly for the user, and doesn't require a bunch of special cases for each of the different providers? I'd like shortcut buttons for the common ID sources, but I don't want to have to write (or even *have in the library*) special Google code, special Facebook code, special Github code, etc. on both server and client. And excluding real user-selected openid services seems like a dick move, even if it's the case that 99.9% of users will just use one of the common services.

I realize the server-side end of this is a pain because who knows what language you're using even. Something simple and convenient for the client end of the deal would be a great start.

As far as I can tell, google and facebook both require the server-owner to register an API key and jump through hoops for the privilege of users being able to log in, which seems like it goes against the openid design which I thought was supposed to be "you can log in to anywhere with an ID from anywhere else that implements support for this, just tell the server which other server to ask", but maybe I'm missing something.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
OAuth is an authorization protocol, allowing the user to say "yes this marketing tool is allowed to send emails using my email address" and stuff like that. In that use case it makes total sense that you need an API key to interact with that specific OAuth provider - because the only thing the OAuth flow actually does is give you a token for making other requests to the parts of the API that require authorization.

Kwolok
Jan 4, 2022

roomforthetuna posted:

Related question - is there a library that makes Oauth/OpenID just for login easy for the developer and user-friendly for the user, and doesn't require a bunch of special cases for each of the different providers? I'd like shortcut buttons for the common ID sources, but I don't want to have to write (or even *have in the library*) special Google code, special Facebook code, special Github code, etc. on both server and client. And excluding real user-selected openid services seems like a dick move, even if it's the case that 99.9% of users will just use one of the common services.

I realize the server-side end of this is a pain because who knows what language you're using even. Something simple and convenient for the client end of the deal would be a great start.

As far as I can tell, google and facebook both require the server-owner to register an API key and jump through hoops for the privilege of users being able to log in, which seems like it goes against the openid design which I thought was supposed to be "you can log in to anywhere with an ID from anywhere else that implements support for this, just tell the server which other server to ask", but maybe I'm missing something.

https://www.passportjs.org/

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

quote:

Passport can be unobtrusively dropped in to any Express-based web application
That's what I get for not being specific enough I suppose. I was hoping for a flat javascript library, not something tied to a framework I don't want to use.

I guess that does at least reveal the answer to my final question about properly open openid, which is as expected a big "gently caress you" from Google and Facebook. (Which also means the other goal of a simple library is going to be a no as well, because any such library necessarily has to handle everything as a special case because the big boys are assholes.)

roomforthetuna fucked around with this message at 14:14 on Feb 24, 2023

LongSack
Jan 17, 2003

roomforthetuna posted:

Related question - is there a library that makes Oauth/OpenID just for login easy for the developer and user-friendly for the user, and doesn't require a bunch of special cases for each of the different providers? I'd like shortcut buttons for the common ID sources, but I don't want to have to write (or even *have in the library*) special Google code, special Facebook code, special Github code, etc. on both server and client. And excluding real user-selected openid services seems like a dick move, even if it's the case that 99.9% of users will just use one of the common services.

I realize the server-side end of this is a pain because who knows what language you're using even. Something simple and convenient for the client end of the deal would be a great start.

As far as I can tell, google and facebook both require the server-owner to register an API key and jump through hoops for the privilege of users being able to log in, which seems like it goes against the openid design which I thought was supposed to be "you can log in to anywhere with an ID from anywhere else that implements support for this, just tell the server which other server to ask", but maybe I'm missing something.

I use Auth0. It abstracts away all the various providers. I just send the user to the Auth0 page (which is somewhat customizable) and the user can choose whether to use google, facebook, etc., or even local user ids that are maintained by me. It’s even free up to a certain number of unique account logins per month.

Granted, I’m using it from React, but I’m pretty sure they offer solutions for other frameworks and perhaps just plain JS.

Adbot
ADBOT LOVES YOU

barkbell
Apr 14, 2006

woof
https://authjs.dev/

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