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
RobertKerans
Aug 25, 2006

There is a heppy lend
Fur, fur aw-a-a-ay.
This is a long shot, but is there any sensible way to prevent rerendering the entire collection held in the state of React Context when I update part of it? My state looks like this:

code:
{
  someID1: {
    foo: 1,
    bar: 2,
 },
 someID2: {
   foo: 1,
   bar: 2,
},
....lots and lots more
And elsewhere in the app, I have something like:

code:
const Alerts = () => {
  const alerts = useContext(AlertsContext);

  return (
    <figure>
      {Object.entries(alerts).map(([id, alert]) => (
        <AlertOverview key={id} {...alert} />
      ))}
    </figure>
  );
}
When I update one of those alert objects, or add more alerts, it updates the state in the Provider, which then goes to that Consumer, which then naturally just rerenders everything. At first I thought I could forcibly prevent rerendering (via componentshouldUpdate or React.memo) on the <AlertOverview /> components themselves, but that doesn't work (the whole state seems to be assumed to be new, so no dice). React.createContext takes a second [callback] argument, calculateChangedBits which seems designed to deal with this exact issue, but it's unstable and involves bitmasks and tbqh I don't see how I can apply it to my usecase

RobertKerans fucked around with this message at 16:39 on Jan 30, 2019

Adbot
ADBOT LOVES YOU

Thermopyle
Jul 1, 2003

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

MrMoo posted:

That's the overhead Browsix is presenting above the WebApis by a browser, which ignores that the apis inherently different concepts.

I'm not buying their rational of WASM is so slow because different IO mechanisms are different. They do seem to acknowledge computation wise the overheads are minimal, the paper is trying to assess the more "real world" performance suites after all.

Ok, I was confused because you said "the Browsix shim for testing posix apps in WASM". Browsix isn't actually for testing posix apps in WASM, that's what Browsix-WASM is. Yes it's confusing naming.

Anyway, I don't know how well the benchmarks of the posix apis will map on to actual future wasm apps, but I'm also not sure how you can seem so confident that there is no correlation.

I guess we'll see.

Tei
Feb 19, 2011


Is a new tech. I am not surprised if really on their first full test they find it dumb slow. You start optimizing when you have a tool to measure, so is normal that before that tool even existed* "peak slowdowns" where hiding somewhere.

Also the parity with native code is a dumb goal, but is a cool goal.

*tools to test it on non-trivial examples

Munkeymon
Aug 14, 2003

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



Anyone know how to make Gatsby poo poo out a minimal bundle with a predictable name?

Doh004
Apr 22, 2007

Mmmmm Donuts...

Munkeymon posted:

Anyone know how to make Gatsby poo poo out a minimal bundle with a predictable name?

Ehhh this sounds funky. As in you don't want the chunked, path based bundles?

I'd steer clear of doing this, but I'd imagine you can do something to this extent by overriding/adding your own rules to the webpack config: https://www.gatsbyjs.org/docs/add-custom-webpack-config/

Doh004 fucked around with this message at 13:33 on Jan 31, 2019

Munkeymon
Aug 14, 2003

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



Doh004 posted:

Ehhh this sounds funky. As in you don't want the chunked, path based bundles?

I'd steer clear of doing this, but I'd imagine you can do something to this extent by overriding/adding your own rules to the webpack config: https://www.gatsbyjs.org/docs/add-custom-webpack-config/

I'm just using it as a static site generator that happens to use a framework I'm familiar with and it's slightly more annoying to clean up the old files when I copy stuff to the server. Plus I almost certainly won't need, say, the map files because I'm not doing anything complicated, so leaving them out of the build output should be fine.

Doh004
Apr 22, 2007

Mmmmm Donuts...

Munkeymon posted:

I'm just using it as a static site generator that happens to use a framework I'm familiar with and it's slightly more annoying to clean up the old files when I copy stuff to the server. Plus I almost certainly won't need, say, the map files because I'm not doing anything complicated, so leaving them out of the build output should be fine.

If you don't have a tool to handle the diffing for you (I host mine on S3 and use their CLI to sync the folder), couldn't you just clear out the folder entirely and reupload it each time. Obviously depends on the size of your site.

prom candy
Dec 16, 2005

Only I may dance
Just host it on netlify?

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

Munkeymon posted:

I'm just using it as a static site generator that happens to use a framework I'm familiar with and it's slightly more annoying to clean up the old files when I copy stuff to the server. Plus I almost certainly won't need, say, the map files because I'm not doing anything complicated, so leaving them out of the build output should be fine.

Use rsync with the --delete option. It is your old file removing friend.

Munkeymon
Aug 14, 2003

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



Doh004 posted:

If you don't have a tool to handle the diffing for you (I host mine on S3 and use their CLI to sync the folder), couldn't you just clear out the folder entirely and reupload it each time. Obviously depends on the size of your site.

It's just a cheap VPS I've been using forever, so I SSH/SFTP everything. Boggles my mind that there's no CLI support for that that I can find, though. I guess the world has passed me by.

prom candy posted:

Just host it on netlify?

Guess I might try at some point.

Lumpy posted:

Use rsync with the --delete option. It is your old file removing friend.

Ooh that's what that's good for :v:

kedo
Nov 27, 2007

If you can ssh into the server how do you not have access to the CLI? On most VPSs I’ve used in the past the two are synonymous.

Munkeymon
Aug 14, 2003

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



kedo posted:

If you can ssh into the server how do you not have access to the CLI? On most VPSs I’ve used in the past the two are synonymous.

I never said I din't have CLI access - I just can't find where there's a nifty Gatsby plugin that'll just deploy some files over SSH/SFTP and clean up the old ones. At least I assume the S3 plugin doesn't just keep stuffing new files in S3 without removing the old ones.

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

Munkeymon posted:



Ooh that's what that's good for :v:

:butt:

kedo
Nov 27, 2007

Reading comprehension is apparently not my greatest strength. Time to remove that line from the ol' resume...

teen phone cutie
Jun 18, 2012

last year i rewrote something awful from scratch because i hate myself
Are there any great tutorials out there that can turn me into a rock-solid webpack and babel master.

I've been writing webpack-built React apps for ~2 years and I can definitely fumble my way through project bootstrapping by doing lots of Googling, but has anyone out there made in-depth comprehensive tutorials on how to bootstrap apps and understand 100% of what you're doing?

e: I'm talking about vocabulary, what plugins are, what presets are, the whole nine yards

teen phone cutie fucked around with this message at 03:36 on Feb 6, 2019

Thermopyle
Jul 1, 2003

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

Grump posted:

Are there any great tutorials out there that can turn me into a rock-solid webpack and babel master.

I've been writing webpack-built React apps for ~2 years and I can definitely fumble my way through project bootstrapping by doing lots of Googling, but has anyone out there made in-depth comprehensive tutorials on how to bootstrap apps and understand 100% of what you're doing?

I had this in my bookmarks, can't recall if I thought it was good or not.

https://www.robinwieruch.de/minimal-react-webpack-babel-setup/

Sulla Faex
May 14, 2010

No man ever did me so much good, or enemy so much harm, but I repaid him with ENDLESS SHITPOSTING
e: hang on i'm pretty tired so i'm going to keep working on it, possibly sleep and try again in the morning, because i'm getting all turned around

e2: oh man i just lost a solid hour and a half because i didnt realise that the Vuex store you create and reference still has to be called store. like, you can't arbitrarily call it whatever you want that makes sense within your app, it has to be store, and it wasn't just a naming convention for the examples. oh man i'm so sloppy, haha

Sulla Faex fucked around with this message at 00:42 on Feb 7, 2019

AtomD
May 3, 2009

Fun Shoe
Has anyone had to persist indexedDB data even after a user clears browser history?
I'm working on a PWA targeting the latest Chrome. Running `await navigator.storage.persisted()` on a dev tools console with the app open returns true, however doing a standard browser history clear still deletes all indexedDB data.
The only thing I've managed to find is this article from 2016 that mentions that this is feature is in development: https://developers.google.com/web/updates/2016/06/persistent-storage.

prom candy
Dec 16, 2005

Only I may dance
React Hooks are out and they're fantastic

teen phone cutie
Jun 18, 2012

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

prom candy posted:

React Hooks are out and they're fantastic

They are indeed.

Here's my first pass at using them for something practical. Cancellable in-flight HTTP requests with Axios and hooks (and TypeScript):

JavaScript code:
import React, { useEffect, useState } from 'react';
import Axios from 'axios'

/**
 * returns an object which contains
 * both the fetch request
 * and the function that will cancel the in-flight request
 */
const fetchData = () => {
  const source = Axios.CancelToken.source();

  return {
    request: () => Axios('https://site.com/endpoint', {
      method: 'GET',
      cancelToken: source.token
    }).then(response => response.data),
    cancel: source.cancel
  }
}


/** 
 * intercept all network requests and add a "wasCancelled"
 * flag if the request was cancelled mid-flight 
 */
Axios.interceptors.response.use(
  (response) => response,
  (err: AxiosError): Promise<APIError[]> => {
    /** was this a result of an Axios cancel invocation */
    const wasCancelled = Axios.isCancel(err);

    return err.response && !wasCancelled
      ? Promise.reject(err.response)
      : Promise.reject([
          {
            reason: 'There was an error',
            wasCancelled
          }
        ]);
  }
);


const MyComponent = (props: MyProps) => {
  const [loading, updateLoading] = useState<boolean>(false);
  const [error, updateError] = useState<APIError[] | undefined >(undefined);
  const [fetchedData, updateFetchedData] = useState<DataType | undefined>(undefined);

  useEffect(() => {
    /** set loading to true, display spinner or whatever */
    updateLoading(true);

    fetchData().request()
      .then((response) => {
        updateLoading(false);
        updateTemplateData(response)
      })
      .catch((err: APIError[]) => {
        /**
         * if the request was cancelled mid-flight, early return
         * the idea is to prevent setting state on unmounted components
         */
        if(err[0].wasCancelled) { return; }
        updateLoading(false);
        updateError(err)
      })

    return () => {
      /** on unmount, cancel the request if it is in-flight */
      fetchData.cancel();
    }
  }, [])
  
  
  ...
  ...
  ...
}

teen phone cutie fucked around with this message at 09:05 on Feb 9, 2019

SimonChris
Apr 24, 2008

The Baron's daughter is missing, and you are the man to find her. No problem. With your inexhaustible arsenal of hard-boiled similes, there is nothing you can't handle.
Grimey Drawer
I don't really understand the point of React Hooks. If your component is sufficiently complex that you need state and lifecycle methods, why not make a class? Isn't the whole point of functional components that they are simple functions from props to JSX? Putting state inside a function just seems like an anti-pattern to me.

teen phone cutie
Jun 18, 2012

last year i rewrote something awful from scratch because i hate myself
Reusing state and less expensive testing to name a couple.

I feel like ppl who’ve used and tested Recompose wrappers can most easily see the benefits

the talent deficit
Dec 20, 2003

self-deprecation is a very british trait, and problems can arise when the british attempt to do so with a foreign culture





Grump posted:

Reusing state and less expensive testing to name a couple.

I feel like ppl who’ve used and tested Recompose wrappers can most easily see the benefits

can you give an example? because i don't see it either

prom candy
Dec 16, 2005

Only I may dance
Let's say you've got some logic that requires you to do some setup in componentDidMount, then some prop diffing and updates in componentDidUpdate, and then maybe some teardown in componentWillUnmount. Already this kinda sucks, you have related logic spread across 3 methods. Now let's say you want to reuse this logic in another component. And for arguments sake, let's say that other component is also doing a couple of things in life cycle methods. Pretty quickly you've had to copy and paste code, or make a higher order component, or a render prop component, and all those things come with their own downsides. Hooks basically let you package up and reuse related stateful logic. Take a look at the Rooks project for some good examples of simple but powerful reusable hooks.

Gildiss
Aug 24, 2010

Grimey Drawer
I still have not read a single thing about Hooks because they were announced 2 days after I just got done updating the two applications I develop to React 16.
All I did was sigh and then become extremely tired.

prom candy
Dec 16, 2005

Only I may dance
You can completely ignore them for now but eventually a library you want to use will probably only exist as a hook. Even then you'll probably go "oh okay this makes sense." For the most part if you already understand React you'll be able to learn hooks in like an hour.

There does seem to be a huge contingent of React devs who are like "gently caress hooks, classes for life!" I have a strong feeling these are some of the same people who were originally like "gently caress React, jQuery for life!" Some people just don't like change.

smackfu
Jun 7, 2004

Writing hooks seems like it has a bunch of gotchas but using them seems pretty straightforward.

prom candy
Dec 16, 2005

Only I may dance
I think the only thing that's both weird and common is the API around useEffect. You have to return a function from it to do any teardown (basically what would've been your componentWillUnmount method) and your second argument is your dependencies. The dependencies thing is weird because if you omit it then your effect runs on every render and if you only want it to run on first render you have to pass an empty array. It seems a little bit overly terse to me but once you learn those rules it's not hard to remember. All the other common hooks (useState, useRef, useContext, etc.) are pretty straightforward and work just about how you'd expect.

I've been switching some components to hooks and writing a couple of custom ones and I really like it. Control flow in my components is way cleaner and there's no more wrapper hell.

Thermopyle
Jul 1, 2003

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

This should explain why you would want to use Hooks.

https://www.youtube.com/watch?v=dpw9EHDh2bM

Kobayashi
Aug 13, 2004

by Nyc_Tattoo
What's the best way to do live reload for a brand new project in TYOOL 2019?

For reference, I'm using VS Code + Typescript to create my own toy framework for fun. I'd like to provide live reload for simple styling, editing static content, and maybe some basic Javascript. Last time I did this was ~4 years ago, using NPM scripts with the live-reload package. I don't know if that's still the best way or if newer approaches have taken over. I'd like to avoid committing to specific frontend framework tooling like React or Ember, or task runners like Grunt, if I can.

huhu
Feb 24, 2006

Kobayashi posted:

What's the best way to do live reload for a brand new project in TYOOL 2019?

For reference, I'm using VS Code + Typescript to create my own toy framework for fun. I'd like to provide live reload for simple styling, editing static content, and maybe some basic Javascript. Last time I did this was ~4 years ago, using NPM scripts with the live-reload package. I don't know if that's still the best way or if newer approaches have taken over. I'd like to avoid committing to specific frontend framework tooling like React or Ember, or task runners like Grunt, if I can.

https://nodemon.io/

teen phone cutie
Jun 18, 2012

last year i rewrote something awful from scratch because i hate myself
Does anyone have experience working with preventing concurrent requests when refreshing a JWT token using rxjs and redux observables?

I have some middleware that looks like this:

JavaScript code:
        import { ajax } from 'rxjs/observable/dom/ajax';
        import { push } from 'react-router-redux';
        import { Observable } from 'rxjs';


        /** if we are getting a 401 from the API */
        if (isAccessTokenExpired(tokens) && !isRefreshTokenExpired(tokens)) {
            /** POST request to refresh the jwt token */
            return ajax({
                method: 'POST',
                url: REFRESH_ENDPOINT,
                body: JSON.stringify({ refresh: tokens.refresh.token }),
                headers: Object.assign({}, headers, {
                    'Authorization': `Bearer ${tokens.refresh.token}`
                })
            }).flatMap(results => {
                const newTokens = Object.assign({}, tokens, decodeTokens(results.response));
                /** store tokens in redux and local storage */
                storeToken(newTokens);
                /** make the original API request we intended to make in the first place */
                return intendedCall(newTokens);
            });
        } else {
            /** if no 401, just make the API request like normal */
            return intendedCall();
        }
This logic works, but it also results in multiple requests to /refresh-token, since I have concurrent network requests running on each page. I really can't find a good solution to prevent this and Googling hasn't gotten me anywhere. My lack of rxjs knowledge is also a pain in the rear end

teen phone cutie fucked around with this message at 05:02 on Feb 12, 2019

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

Grump posted:

Does anyone have experience working with preventing concurrent requests when refreshing a JWT token using rxjs and redux observables?

I have some middleware that looks like this:

JavaScript code:
        import { ajax } from 'rxjs/observable/dom/ajax';
        import { push } from 'react-router-redux';
        import { Observable } from 'rxjs';


        /** if we are getting a 401 from the API */
        if (isAccessTokenExpired(tokens) && !isRefreshTokenExpired(tokens)) {
            /** POST request to refresh the jwt token */
            return ajax({
                method: 'POST',
                url: REFRESH_ENDPOINT,
                body: JSON.stringify({ refresh: tokens.refresh.token }),
                headers: Object.assign({}, headers, {
                    'Authorization': `Bearer ${tokens.refresh.token}`
                })
            }).flatMap(results => {
                const newTokens = Object.assign({}, tokens, decodeTokens(results.response));
                /** store tokens in redux and local storage */
                storeToken(newTokens);
                /** make the original API request we intended to make in the first place */
                return intendedCall(newTokens);
            });
        } else {
            /** if no 401, just make the API request like normal */
            return intendedCall();
        }
This logic works, but it also results in multiple requests to /refresh-token, since I have concurrent network requests running on each page. I really can't find a good solution to prevent this and Googling hasn't gotten me anywhere. My lack of rxjs knowledge is also a pain in the rear end

I don’t know squat about rxjs, but you are storing a “I am trying to get a new token” flag in app state / redux store when you make your first request and check for it before you fire a second one, right?

teen phone cutie
Jun 18, 2012

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

Lumpy posted:

I don’t know squat about rxjs, but you are storing a “I am trying to get a new token” flag in app state / redux store when you make your first request and check for it before you fire a second one, right?

What’s the benefit there? I have multiple requests that are firing concurrently on page load, so there would be some race conditions if I added a flag when the token was refreshing

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

Grump posted:

What’s the benefit there? I have multiple requests that are firing concurrently on page load, so there would be some race conditions if I added a flag when the token was refreshing

You said you wanted to avoid duplicating token refresh requests, right? The benefit of knowing one is in progress is to avoid sending another. Maybe I don’t understand your question/ problem.

teen phone cutie
Jun 18, 2012

last year i rewrote something awful from scratch because i hate myself
ah okay yeah I don't think I explained well.

I have 3 API requests that are running concurrently on page load. The point of that middleware is to intercept every single request and say

1. If the auth token is expired, run some request to get a new one
2. When this happens, re-run the original request
3. Queue the remaining 2 network requests until after the refresh request has finished

My issue here is that the other 2 network requests are firing before I can refresh the token

huhu
Feb 24, 2006

Grump posted:

ah okay yeah I don't think I explained well.

I have 3 API requests that are running concurrently on page load. The point of that middleware is to intercept every single request and say

1. If the auth token is expired, run some request to get a new one
2. When this happens, re-run the original request
3. Queue the remaining 2 network requests until after the refresh request has finished

My issue here is that the other 2 network requests are firing before I can refresh the token

Sounds like you pretty much want what he suggested. Add a Boolean like isFetchingNewToken and wasNewTokenFetched. The first can be used to make sure no requests go out while the fetching is happening and the second will trigger the requests to happen once the token is retrieved.

teen phone cutie
Jun 18, 2012

last year i rewrote something awful from scratch because i hate myself
ok gonna try that tonight. I fully admit this might just be me not considering the most obvious solution

teen phone cutie
Jun 18, 2012

last year i rewrote something awful from scratch because i hate myself
Yeah adding that flag totally worked. This was for an interview test, so I probably shouldn’t have, but I basically stripped out all the rxjs and other already provided redux middleware for my own custom redux middleware and Axios. I ended up simplifying it a lot and hoping the interviewer sees that.

I’ve actually never had a test like this that expected me to jump into a feature with a bunch of really opinionated code. From my experience, rxjs and redux don’t mix well and I’m hoping to talk about that if I get to the next round

Adbot
ADBOT LOVES YOU

I R SMART LIKE ROCK
Mar 10, 2003

I just want a hug.

Fun Shoe
I can't really speak for them but a possible idea is that they wanted to see what you would do when given constraints. As you mention it gives you a good opportunity to explain your thought process and why you re-wrote the code

It's either that or they thought they were helping you out :shrug:

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