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
ddiddles
Oct 21, 2008

Roses are red, violets are blue, I'm a schizophrenic and so am I
Kind of a bandaid over a lovely setup, but couldn't NPM just put something like "if you host your package on NPM and its used, you can only archive your package, not remove it", and solve these sort of issues?

Or even just let them delete it, but keep it up for thirty days or something to give people time to replace. Waking up to something just being gone is pretty insane.

Adbot
ADBOT LOVES YOU

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!

ddiddles posted:

Kind of a bandaid over a lovely setup, but couldn't NPM just put something like "if you host your package on NPM and its used, you can only archive your package, not remove it", and solve these sort of issues?

Or even just let them delete it, but keep it up for thirty days or something to give people time to replace. Waking up to something just being gone is pretty insane.
I think the problem is when you import packages that are hosted on npm but depend on packages that are hosted elsewhere, so you get unintentional transitive dependencies on stuff that goes away from elsewhere?

But maybe npm lets actual npm-hosted packages just wander away too, I don't know.

Volguus
Mar 3, 2009

Ola posted:

Camera zooms out. That was just one brick. Zooms out more. A brick in the support column of a huge bridge. Zooms out even more. In a vast metropolis of brick structures.

The only solution is to take down the metropolis.

necrotic
Aug 2, 2005
I owe my brother big time for this!

roomforthetuna posted:

But maybe npm lets actual npm-hosted packages just wander away too, I don't know.

They supposedly changed their policies after the left-pad incident to only allow de-listing of published versions, after I think a 24 hour period. If I recall there was an event shortly after left-pad where this was ignored.

Thermopyle
Jul 1, 2003

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

ddiddles posted:

Kind of a bandaid over a lovely setup, but couldn't NPM just put something like "if you host your package on NPM and its used, you can only archive your package, not remove it", and solve these sort of issues?

Yeah, they did this after the left-pad fiasco. If a package is published more than 72 hours ago you cannot unpublish it.

This most recent incident was only npm's fault in the sense that npm allows you to specify an url as a dependency rather than a package name and version.

The url that some packages had in their package.json stopped working, so those packages stopped working, and packages that depended upon them stopped working, and packages that depended upon them stopped working, and packages that depended upon them stopped working, and packages that depended upon them stopped working, and packages that depended upon them stopped working...

Munkeymon
Aug 14, 2003

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



Doom Mathematic posted:

* proactively converts str to a string if it isn't a string for some reason

Because it might be a Number

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
code:
module.exports = leftpad;

function leftpad (str, len, ch) {
    if (typeof str !== 'string') {
        throw new Error('Instance of String expected');
    }

    return str.padStart(str.length + len, ch);
}
The method is built into javascript. padStart

ddiddles
Oct 21, 2008

Roses are red, violets are blue, I'm a schizophrenic and so am I
Man I've taken this whole ecosystem for granted, was under the impression that NPM packages could only depend on other hosted npm packages.

Allowing just a url to something that can disappear is...wtf.

Happy Thread
Jul 10, 2005

by Fluffdaddy
Plaster Town Cop

Nolgthorn posted:

The method is built into javascript. padStart

That too lol

I've had the same realization about parts of engines like JQuery so many times that I don't feel like I'm missing much at all by being wholly adverse to importing outside code

necrotic
Aug 2, 2005
I owe my brother big time for this!
The String method was added in ES2017, so it's relatively new. The left-pad debacle happened before it was introduced.

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

Dumb Lowtax posted:

That too lol

I've had the same realization about parts of engines like JQuery so many times that I don't feel like I'm missing much at all by being wholly adverse to importing outside code

Yeah, the big problem when evaluating libraries is knowing what to reuse and what you should write yourself. There's always a cost when using a third party library - it can be difficult to assess how well you understand the problem the library is trying to solve, dependency management can be a huge bitch, and it can be difficult to assess how well tested the library is or whether it's handling cases that are pertinent to your problem domain.

I would say new developers or developers fresh out of school are generally going to use every library under the sun and then get burned when a problem comes up that's difficult to explain because it in no way relates to your problem domain, but is just a consequence of including every library under the sun. This jades people and turns them into "gently caress it, write it myself" types - these types get burned when they try to fix issues or make their own (crypto, deserialization/serialization, authentication, XSS, input sanitization etc.) Judgement eventually gets better through experience.

Thermopyle
Jul 1, 2003

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

Bruegels Fuckbooks posted:

Judgement eventually gets better through experience.

Well...if its going to get better that's how it happens.

There's plenty of old farts around that insist on rolling every. single. thing. themselves.

Happy Thread
Jul 10, 2005

by Fluffdaddy
Plaster Town Cop
I don't plan on doing it forever, you all have convinced me to at least start looking around for solutions when I get to "authentication" being something my engine has to do

LifeLynx
Feb 27, 2001

Dang so this is like looking over his shoulder in real-time
Grimey Drawer
I know "this" binding is weird in React, but I thought arrow functions fix most of those problems? I've got this:

code:
<img
className={`card-object-img-sm card-object-img-${uniqueid}`}
alt={cardData.name}
src={cardData.card_faces[0].image_uris.small}
onClick={() => this.src = cardData.card_faces[1].image_uris.small}
/>
Clicking on the image gives "TypeError: Cannot set property 'src' of undefined". How do I make sure "this" refers to the image?

necrotic
Aug 2, 2005
I owe my brother big time for this!
this is pointing at the React component / function scope. You should _never_ change element properties using e.g. `el.src` in react. You need a piece of state that you change on click.

untested code but the right idea:


code:
function MyImage() {
  const [imgSource, setImgSource] = useState(cardData.card_faces[0].image_uris.small);

  return (<img ... src={imgSource} onClick={() => setImgSource(cardData.card_faces[1].image_uris.small)}/>);
}

necrotic fucked around with this message at 21:18 on May 28, 2019

LifeLynx
Feb 27, 2001

Dang so this is like looking over his shoulder in real-time
Grimey Drawer

necrotic posted:

this is pointing at the React component / function scope. You should _never_ change element properties using e.g. `el.src` in react. You need a piece of state that you change on click.

untested code but the right idea:


code:
function MyImage() {
  const [imgSource, setImgSource] = useState(cardData.card_faces[0].image_uris.small);

  return (<img ... src={imgSource} onClick={() => setImgSource(cardData.card_faces[1].image_uris.small)}/>);
}

That might not work because this is in a mapped array with sometimes dozens of images, and that won't work unless each has its own unique useState, right?

Is there a place I can show code for a critique/suggestion? I made something functional that I'm proud of, but I've only been teaching myself React for about a month so I'm sure I've made a bunch of mistakes or didn't do things the React way. It's been about two months since I've thought about using Javascript for more than simple DOM manipulation.

necrotic
Aug 2, 2005
I owe my brother big time for this!
Yeah, the small snippet you gave doesn't really provide any context. What's the overall goal?

Osmosisch
Sep 9, 2007

I shall make everyone look like me! Then when they trick each other, they will say "oh that Coyote, he is the smartest one, he can even trick the great Coyote."



Grimey Drawer

LifeLynx posted:

That might not work because this is in a mapped array with sometimes dozens of images, and that won't work unless each has its own unique useState, right?

Is there a place I can show code for a critique/suggestion? I made something functional that I'm proud of, but I've only been teaching myself React for about a month so I'm sure I've made a bunch of mistakes or didn't do things the React way. It's been about two months since I've thought about using Javascript for more than simple DOM manipulation.

Jsfiddle or glitch.io are common places to put demo code, or github.io if you want it more associated with you.

Macichne Leainig
Jul 26, 2012

by VG
I feel like I'm doing something wrong with this web worker I'm writing.

So, the basic gist is that, the web worker is used to connect to IoT devices on your LAN, and send commands over TCP. We want the commands to be as concurrent as possible, so just rapid-fire send them off. I chose a web worker as I can write pure javascript for this logic and only post a message to it from the accompanying Electron UI when necessary.

I have the web worker set to basically wait a second if the queue is empty, so that if commands are queued in that second, it can rapid-fire execute the commands. This works great, except it's a recursive call, so it hits the call stack limit pretty quickly. I feel like I'm doing something very wrong here. There's probably a design pattern I'm missing, but I got gently caress all for a true computer science education despite having a degree in comp sci.

The processing method is this:

code:
_processQueue() {
  const self = this;
  if (this.setup) return;

  // Wait for the queue to fill up
  if (this.commandQueue.length === 0) {
    setTimeout(() => self._processQueue(), self._commandWaitDelay);
    if (this._debug) console.log("Queue empty, awaiting command...");
  } else {
    const nextCommand = this.commandQueue.pop();

    if (this.hubs[nextCommand.hub].isReady) {
      this.hubs[nextCommand.hub].sendCommand(nextCommand.commandText);
    } else {
      this.commandQueue.push(nextCommand);
    }

    self._processQueue();
  }
}
So, what's the correct way of doing what I'm doing? Because this sure as hell isn't it.

If a library for this exact thing exists on NPM, that's also an option. The less code for this poo poo I have to write the better, since surely someone else has figured this out in a better way than I have.

necrotic
Aug 2, 2005
I owe my brother big time for this!
Two options I see:

1. Use a loop instead of recursively calling.
2. Always use setTimeout, but change the delay to 0 if the queue is not empty.

edit: also, is a first-in-last-out queue the right option here? Using shift instead of pop is more common for something like this.

edit2: also, the first option i gave would also hit the stack limit :downs: you just need to go with the second option, which always resets the stack. I'd do something like this:

code:
_processQueue() {
  if (this.setup) return;

  const retryCommands = [];

  this.commandQueue.forEach(nextCommand => {
    if (this.hubs[nextCommand.hub].isReady) {
      this.hubs[nextCommand.hub].sendCommand(nextCommand.commandText);
    } else {
      retryCommands.push(nextCommand);
    }
  });

  // Replace the queue with retries
  this.commandQueue = retryCommands;

  setTimeout(
    () => this._processQueue(),
     retryCommands.length > 0 ? 0 : this._commandWaitDelay
  );
}

necrotic fucked around with this message at 01:40 on May 29, 2019

Macichne Leainig
Jul 26, 2012

by VG
It did used to be in a setTimeout so it makes sense that when I got rid of that in the final call that I started getting the error.

It doesn’t really matter what direction the queue is, I can change that.

I just didn’t know if there was some other way I could just kick off a loop that processes the queue. I almost thought about kicking off another worker and sending messages to that, but that seems like overkill.

Kudaros
Jun 23, 2006
I have almost nothing but scientific computing experience and just finished my first javascript experience last week, so I've got a stupid question.

I'm working through this react tutorial building a movie database table where we can delete table entries. The below portion, within the handleDelete method, is what I'm curious about. Within the filter method, the arrow function is defined using the 'm' symbol. What is this symbol referencing? the _id is a property of the movies array of objects that the getMovies() function returns, so I get that it's pulling from that, but how does it know?

For that matter, what is the `this` symbol referencing here? This confuses me in class context.

code:
class Movies extends Component {
  state = {
    movies: getMovies()
  };

  handleDelete = movie => {
    const movies = this.state.movies.filter(m => m._id !== movie._id);
    this.setState({ movies });
  };

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

Kudaros posted:

I have almost nothing but scientific computing experience and just finished my first javascript experience last week, so I've got a stupid question.

I'm working through this react tutorial building a movie database table where we can delete table entries. The below portion, within the handleDelete method, is what I'm curious about. Within the filter method, the arrow function is defined using the 'm' symbol. What is this symbol referencing? the _id is a property of the movies array of objects that the getMovies() function returns, so I get that it's pulling from that, but how does it know?

For that matter, what is the `this` symbol referencing here? This confuses me in class context.

If you call Array.filter() on something, it invokes the function you provide on every element in the array, and the return value is an array containing the elements that passed the test. You are naming the argument that you're providing though - filter function itself doesn't care what the arguments are named (e.g. you could could it 'movie' instead of 'm', or 'value'... doesn't matter as long as you provide a function with expected number of arguments for filter).

For "this", check how "Component" is defined in react...

Happy Thread
Jul 10, 2005

by Fluffdaddy
Plaster Town Cop
I don't know React but generally when I see a "class" in JavaScript, the "this" keyword appearing in method-scope of that class refers to an instance of that class, so it looks like your "this" is an instance of a "Movies" which I guess wraps all your movies.

Roadie
Jun 30, 2013
"this" in a class context is the instance, yes. Static members would be Movies.whatever, not this.whatever.

Kudaros
Jun 23, 2006
Ah I see. It's becoming more intuitive now, thanks.

I'll spend more time on the docs.

Macichne Leainig
Jul 26, 2012

by VG
For anyone else who might be doing some queue-based processing work I was previously confused about, I discovered this package:

https://yarnpkg.com/en/package/queue

I turned on the autostart option so that it fires off the tasks as soon as they're entered into the queue, and this is immediately noticeably faster than my home-grown method. Plus, it let me cut out about half of the code that I wrote to manage the queue that was also probably wrong.

So, thanks for your help necrotic, your code did help me out a bit, but this seems to be the best solution for my specific use case.

Munkeymon
Aug 14, 2003

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



Protocol7 posted:

For anyone else who might be doing some queue-based processing work I was previously confused about, I discovered this package:

https://yarnpkg.com/en/package/queue

I turned on the autostart option so that it fires off the tasks as soon as they're entered into the queue, and this is immediately noticeably faster than my home-grown method. Plus, it let me cut out about half of the code that I wrote to manage the queue that was also probably wrong.

So, thanks for your help necrotic, your code did help me out a bit, but this seems to be the best solution for my specific use case.

Oh that reminds me - I bet RxJS would handle it pretty well, too, but it's got a lot more going on than a queue.

tankadillo
Aug 15, 2006

tankadillo posted:

I recently changed my React app to store parts of its state in indexeddb (via LocalForage). Components use a useEffect hook to load their state from indexeddb and then a useEffect hook to write changes any time the state updates. This seems to be working fine, except I can't figure out how to get my tests to play nicely with it. (I'm using react-testing-library.) I assume I should use something like waitForElement to wait for the state to load (since indexeddb is async), but Jest gets mad at me because I don't have all my state changes wrapped in act(). The problem is, I can't easily change `const {getByText} = render(<MyComponent/>);` to `const {getByText} = act(() => render(<MyComponent/>));`, or can I?

I figure this is probably a solved problem, but the guides I've found don't seem to cover it.

In case anyone cares, I solved this problem by creating a manual mock for my hooks which removes all the async functions. It won’t actually test the storage, but 99% of what I’m testing is how the data gets processed, not stored, anyway.

Tea Bone
Feb 18, 2011

I'm going for gasps.
I'm adding webhook functionality to a rails app. At the moment I just have the one channel and inside the receive function I use the data passed to it to dispatch a custom event (something like "webhook:modelNameActionName"). This way I can just use event listeners inside the .js files relevant to that modal to trigger the desired behaviour.

It all works fine and seems tidier this way to me than putting the desired behaviour logic right there in the receive function, but I was just wondering if there's any reason I shouldn't be doing it this way?

I'm not too clued in on JavaScript best practices but it feels like adding dozens of listeners might not be great?

Chas McGill
Oct 29, 2010

loves Fat Philippe
What are yall using for typescript linting? Is eslint ready to replace tslint yet in practice?

Tanners
Dec 13, 2011

woof

Chas McGill posted:

What are yall using for typescript linting? Is eslint ready to replace tslint yet in practice?

Im still on tslint/tsc and haven't felt enough pain to think about switching back to eslint.

LifeLynx
Feb 27, 2001

Dang so this is like looking over his shoulder in real-time
Grimey Drawer
Just end my life with these "event listeners don't force React to rerender" problems.

code:
import React, {useState, useEffect, useReducer} from 'react';

function Game() {

    useEffect(() => {
        setGameName("DoNotUse")
    }, []);

    let [gameName, setGameName] = useState("DoNotUse")
    const [ignored, forceUpdate] = useReducer(x => x + 1, 0);

    const GrabData = () => {
        //Grab data here
    }
        
    function GenerateStacks(thename) {
        setGameName(thename)
        forceUpdate() //This doesn't force an update, so I should name it something else like "Every StackOverflow answer on this is useless"
        fire.database().ref(gameName).child("faceDownList1").set("")

        GrabData();

        return("Hello") //Maybe this will force rerender?
    }

    return (
        <main id="main-section">

        <section id="header">
        <h1>App Title</h1>
        <nav id="draft-nav">

        <form id="create-game" onSubmit={
            (e) => {
                e.preventDefault()
                setGameName("IfThisWorksIllCry")
                GenerateStacks("AlphaTestPleaseWorkOMG")
            }
        }>
            <input type="text" id="game-id"></input>
            <button id="startbtn2" type="submit">Start New Game</button>
        </form>
        
        </nav>
        </section>
        </main>
    )

    
}

export default Game
All I want to do is when that button is clicked, update the game name. It doesn't work unless you click it twice. Nothing I've tried, no dirty forbidden React trick, whatsoever works. That forceUpdate is ugly but it doesn't do anything. I've tried returning something, that doesn't work. useEffect is my go-to solution. Usually if I force the setWhatever function to load once when the app loads, I can setWhatever later on an onClick or onSubmit and it'll work. This time, nothing. I'm about to put a big "gently caress it, click the button twice to start the game" disclaimer on the page because this is maddening.

Edit: Wait, it forces an update... but is passing on the OLD data ("DoNotUse") to Firebase. How can I get it to send the new data?

LifeLynx fucked around with this message at 20:44 on Jun 4, 2019

ddiddles
Oct 21, 2008

Roses are red, violets are blue, I'm a schizophrenic and so am I
code:
function GenerateStacks(thename) {
        setGameName(thename)
        forceUpdate() //This doesn't force an update, so I should name it something else like "Every StackOverflow answer on this is useless"
        fire.database().ref(gameName).child("faceDownList1").set("")

        GrabData();

        return("Hello") //Maybe this will force rerender?
    }
The value you are setting with setGameName wont be available until the next render, which wont happen until that function completes. So you call setGameName which queues up a rerender, but you're calling the firebase API before that happens.

Have a useEffect watching gameName and react to it changing, you could have your form just call setGameName("WhateverGameName"), and a useEffect that calls GenerateStacks.

LifeLynx
Feb 27, 2001

Dang so this is like looking over his shoulder in real-time
Grimey Drawer

ddiddles posted:

code:
function GenerateStacks(thename) {
        setGameName(thename)
        forceUpdate() //This doesn't force an update, so I should name it something else like "Every StackOverflow answer on this is useless"
        fire.database().ref(gameName).child("faceDownList1").set("")

        GrabData();

        return("Hello") //Maybe this will force rerender?
    }
The value you are setting with setGameName wont be available until the next render, which wont happen until that function completes. So you call setGameName which queues up a rerender, but you're calling the firebase API before that happens.

Have a useEffect watching gameName and react to it changing, you could have your form just call setGameName("WhateverGameName"), and a useEffect that calls GenerateStacks.

Oh that's interesting. Coincidentally this is for a Magic: The Gathering type thing, and in Magic there's a group of rules called "state based actions" that watch for a state change and something happens (usually a player losing the game or a creature dying) as a result of it. They aren't checked in the middle of a spell resolving though, instead they wait for a spell to resolve and see whether or not they should happen... I'm starting to see programming logic everywhere.

How would I write this useEffect though? I've only ever used them for triggering an action once as in the example code I posted.

ddiddles
Oct 21, 2008

Roses are red, violets are blue, I'm a schizophrenic and so am I
Untested but something like this should work, really depends on what GrabData is doing.

The second argument to useEffect is an array of variables react will watch and call the passed in function if any of them have changed (shallow check, no deeply nested stuff), giving it an empty array says "there are no dependencies, so run this on first render", the one below will call GenerateStacks every time gameName changes.

code:
import React, {useState, useEffect, useReducer} from 'react';

function Game() {
    let [gameName, setGameName] = useState("DoNotUse")

    useEffect(function() {
      // Do any validation of gameName variable if you want here.
      GenerateStacks();
    }, [gameName])

    const GrabData = () => {
        //Grab data here
    }
        
    function GenerateStacks() {
        fire.database().ref(gameName).child("faceDownList1").set("")
        GrabData();
    }

    return (
        <main id="main-section">

        <section id="header">
        <h1>App Title</h1>
        <nav id="draft-nav">

        <form id="create-game" onSubmit={
            (e) => {
                e.preventDefault()
                setGameName("NewGameName")
            }
        }>
            <input type="text" id="game-id"></input>
            <button id="startbtn2" type="submit">Start New Game</button>
        </form>
        
        </nav>
        </section>
        </main>
    )

    
}

export default Game
From what i've learned doing hooks in a production app, put everything you possible can in small useEffect calls when you are dealing with hook state.

ddiddles fucked around with this message at 21:24 on Jun 4, 2019

smackfu
Jun 7, 2004

I can’t help but feel like hooks are making this more complicated than the old way of doing it.

evilfunkyogi
Jun 27, 2005
:effort:

smackfu posted:

I can’t help but feel like hooks are making this more complicated than the old way of doing it.

I feel this way almost every time I see examples of code using hooks, but to be fair I haven't had the time to really dig into them.

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

smackfu posted:

I can’t help but feel like hooks are making this more complicated than the old way of doing it.

I think they are not more complicated, but they are new enough and just different enough to cause issues when you bring your old mental model along with you when starting to use them. Plus there’s the ‘new and shiny’ factor so people are trying to cram them in even when maybe they didn’t need to.

Adbot
ADBOT LOVES YOU

Roadie
Jun 30, 2013
Hooks make some things more complicated, but they're real nice for being able to combine componentDidMount and componentDidUpdate logic and derived data stuff in a way that cares less about the overall lifecycle of the component.

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