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.
Javascript 2 announced:

https://devblogs.microsoft.com/typescript/a-proposal-for-type-syntax-in-javascript/

Adbot
ADBOT LOVES YOU

camoseven
Dec 30, 2005

RODOLPHONE RINGIN'

It's weird to be on the same team as Microsoft, but drat this proposal kicks rear end

Sab669
Sep 24, 2009

EDIT :toot: figured it out. You can refer to an object's fields through a string like so: theObject["propertyName"], so in my case my ckeditor definition simply needed to be <ckeditor [(ngModel)]="asrModel[field.modelProperty]" ..>

For lack of a better term, does Angular support reflection? Like I want to use the value of oneObject.SomeStringProperty to get the actual value of otherObject.TheActualPropertyIWant
I don't know if what I'm trying to accomplish is technically possible.



Right now, I've got a hardcoded rich text editor bound to a property on my object, which gets loaded onInit.

component.HTML:
code:
    Special Considerations:
    <div>
        <ckeditor [(ngModel)]="asrModel.specialConsiderations" [editor]="Editor" (ready)="onReady($event)">    
      </ckeditor>
    </div>
component.ts:
code:
export class AsrGenerationComponent extends Base implements OnInit {
  public asrModel: AsrModel = new AsrModel();
  
  ngOnInit(): void {
    this.getAsrData();
  }

  getAsrData(): void {
    this.asrService.getDataByLoanNumber(lnum).subscribe(l => {
      if (l){
        this.asrModel = l;
      }
  }
}
That's a really stripped down version of the whole component, but I think you get the idea; I'm fetching data for my asrModel object and the ckeditor is bound to a property on that object. This all works. Page loads, I see asrModel.specialConsiderations's value in my control.


What I'm trying to do now, instead of hardcoding my UI is just load a JSON object that defines a collection of Sections, which has a collection of Subsections, which has a collection of Fields.
That got that working, but I can't abstract out the `[(ngModel)]="asrModel.specialConsiderations"` of the HTML shown in my first snippet above into my JSON.

My field JSON looks like this:
code:
						"fields": [
							{
								"headerDisplay": "Special Considerations",
								"subHeaderDisplay": null,
								"name": "Special Considerations",
								"fieldType": "textField",
								"objects": null,
								"defaultValue": "Enter Name...",
								"fieldFormatting": "text",
								"initialDataSource": null,
								"isPreselected": false,
								"formControlName": "documentName",
								"canEdit": true,
								"modelProperty": "asrModel.specialConsiderations"
							}
						]
It's just a very generic definition of most input controls on a web application so that if we need to print a textbox, radio button, drop down, date picker etc. we can define all that here.

And my updated component.html:
code:
            <!-- loop over the Fields collection seen in my JSON above^-->
            <div *ngFor="let field of subSection.fields" style="margin-left: 15px;" [ngSwitch]="field.fieldType">

              <!-- switch on the fieldType value from the JSON to determine what kind of control to render -->
              <div *ngSwitchCase="'textField'" style="margin-left: 20px;" class="form-group">

                <!-- parse the field data>
                {{field.headerDisplay}}
                <p *ngIf="field.subHeaderDisplay != null">{{field.subHeaderDisplay}}</p>
                <div>

                  <!-- this is the line I'm having trouble changing from my first HTML snippet -->
                  <ckeditor [(ngModel)]="field.modelProperty" [editor]="Editor" (ready)="onReady($event)">
                
                  </ckeditor>
                </div>
              </div>
The output of this is that my ckeditor control renders the literal string text "asrModel.specialConsiderations", whereas I simply want to use that as a reference to go get the specialConsiderations field from my asrModel object.

I hope that all makes sense :( Like I said I'm pretty new to Angular, I strongly suspect it's possible I just don't know how / can't find it on SO.

Sab669 fucked around with this message at 17:33 on Mar 10, 2022

Doom Mathematic
Sep 2, 2008

This is relevant to my interests.

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!

camoseven posted:

It's weird to be on the same team as Microsoft, but drat this proposal kicks rear end
It's funny because while it totally makes sense for browsers to not do type checking and just treat the type syntax the same way they treat comments, you know they would end up just doing type checking anyway, maybe guarded by a setting, because the Chrome debugger is already like 80% of dev tools.

aperfectcirclefan
Nov 21, 2021

by Hand Knit
I barely if ever use JQuery, but i'm running into a issue that I think should be easy to solve but I can't. I'm trying to get a field value via JQuery and THEN set it to a bit of local storage so I can use it on another form. THis is the code I have:

code:
var category; 
jQuery("input[name='input_6']").click(function(){
category = this.value; setStorage(this.value);
}); 

function setStorage(memlevel){
localStorage.setItem('memberlevel', memlevel);
}
Now unfortunately, when I retrieve the local storage, I get null back. However if I do console.log(category) that works...so i'm wondering what i'm missing here with setting localStorage?

Thanks for any help goon.s

I R SMART LIKE ROCK
Mar 10, 2003

I just want a hug.

Fun Shoe
phone postin but what's your getter look like for locale storage? Also what does the dev console say is set in locale storage after the event has fired?

aperfectcirclefan
Nov 21, 2021

by Hand Knit
I got it to populate finally and work, I think it was a caching issue :suicide:.

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
We have an interface that allows zooming in and out using the scroll wheel or the trackpad. This functionality only works if you are holding down the Ctrl key on windows or the Meta key on mac. There is one horrendous issue that is going to drive me crazy.

https://medium.com/@auchenberg/detecting-multi-touch-trackpad-gestures-in-javascript-a2505babb10e

One day IE10 pioneered this idea to bubble the pinch event up through the mouse wheel event, for convenience. Which is great, now the mouse wheel and pinching on a trackpad both trigger the same event. That's exactly my use case. However when it's a pinch event the scale is way off, by a factor of 10, so that has to be corrected so how do I tell the difference between a pinch and a scroll of the wheel?

Well Microsoft decided that to help you out, just check the value of event.ctrlKey. Which is the key that the users of our app always happen to be holding down when they want to zoom and it is completely useless to me.

How in the world am I supposed to make use of wheel events and pinch events in conjunction with the ctrl key, if javascript is using the ctrl key to tell me whether it is a trackpad event :/

Edit:

I know I can detect keyboard events separately, that would tell me if the key was actually being held down or not. But if they are actually holding it down, I have no way to tell if they're using the trackpad or the mouse.

What kind of implementation is that? I'm not saying I'm better than Microsoft but I don't understand what they were thinking in that conference room.

Nolgthorn fucked around with this message at 14:10 on Apr 5, 2022

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
JavaScript code:
let delta = 0;
let scale = -1;
let timeout;

function onWheel(ev) {
    if (!ev.ctrlKey) return;
    ev.preventDefault();

    clearTimeout(timeout);
    timeout = setTimeout(() => {
        // persist zoom
        const newZoom = currentZoom + delta;
        delta = 0;
        scale = -1;

        performZoom(newZoom, ev);
    }, ZOOM_DEBOUNCE);

    // We track the scale of the delta
    // to normalize velocity across devices and
    // input types.
    if (scale < 0) {
        scale = Math.abs(ev.deltaY);
    } else {
        scale = Math.min(scale, Math.abs(ev.deltaY));
    }

    delta -= ZOOM_SPEED * (ev.deltaY / scale);
}
Here is my brilliant idea:

When the wheel event fires I keep track of how big the deltaY was.

From that point until they stop spinning the wheel I use whatever the smallest delta was as a divisor. That way I get a consistent 1 or -1, or 2 or -2 etc. Then I don't have to care about what type of mouse they are using or what input device it is or any of that.

It's pretty much saying "I don't care how much they moved it I just care that they moved it." But additionally accounts for very large movements, as I've noticed it does that sometimes and delivers a value two or three times bigger than the others.

Then I just multiply that by a zoom speed.

Nolgthorn fucked around with this message at 08:24 on Apr 7, 2022

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.

Nolgthorn posted:

code:
let delta = 0;
let scale = -1;
let timeout: NodeJS.Timeout;

function onWheel(ev: WheelEvent) {
    if (!ev.ctrlKey) return;
    ev.preventDefault();

    clearTimeout(timeout);
    timeout = setTimeout(() => {
        // persist zoom
        const newZoom = currentZoom + delta;
        delta = 0;
        scale = -1;

        performZoom(newZoom, ev);
    }, ZOOM_DEBOUNCE);

    // We track the scale of the delta
    // to normalize velocity across devices and
    // input types.
    if (scale < 0) {
        scale = Math.abs(ev.deltaY);
    } else {
        scale = Math.min(scale, Math.abs(ev.deltaY));
    }

    delta -= ZOOM_SPEED * (ev.deltaY / scale);
}
Here is my brilliant idea:

When the wheel event fires I keep track of how big the deltaY was.

From that point until they stop spinning the wheel I use whatever the smallest delta was as a divisor. That way I get a consistent 1 or -1, or 2 or -2 etc. Then I don't have to care about what type of mouse they are using or what input device it is or any of that.

It's pretty much saying "I don't care how much they moved it I just care that they moved it." But additionally accounts for very large movements, as I've noticed it does that sometimes and delivers a value two or three times bigger than the others.

Then I just multiply that by a zoom speed.

If you try that with an apple magic mouse, you're going to have a fun time. That mouse likes to emit a scroll event really really tiny deltaY (like .0001) when you scroll it horizontally (or in most cases swipe your finger slightly to the left or right because it has no buttons.)

The scroll wheel event does all sorts of crazy poo poo and you'll see differences depending on OS, whether scroll wheel is set to go by line or by page, type of mouse, etc. I'd highly recommend just letting it scroll the page and not trying to use it to do other things if you can possibly help it.

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
I'm trying to have it zoom the page. But can't get around pinch on the tackpad and mouse wheel both emitting the same event, only differentiated by the ctrl parameter. Our app uses the ctrl key to enable the functionality in the first place. So there's no way to tell which input type it is. That's the problem. I'm not trying to change the way the page scrolls, that's a nightmare.

Nolgthorn fucked around with this message at 19:00 on Apr 5, 2022

LongSack
Jan 17, 2003

I am in the middle of rewriting one of my Blazor server front ends into React. I don't think this is a React question, but more JavaScript related, so here goes.

I am making a retail store page as a demo (it also has an employee portal and vendor portal). On the index page, just for variety, the page selects three products at random and displays them to the user as items specially selected for them.

I have this function:
JavaScript code:
export function getData(url: string) {
  return fetch(url).then((response) => {
    if (!response.ok) {
      throw Error("There was an error fetching data: " + response.statusText);
    }
    return response.json();
  });
}
which works just fine. But rather than call getData all over the place, I'm trying to write services which abstract out the details. To that end, I've written my first service, ProductService which contains this function:
JavaScript code:
import { getData } from "./api";
import { IProduct } from "../Interfaces/IProduct";
import { uriBuilder } from "./tools";

export function RandomProducts(count: number): IProduct[] | null {
  const uri = uriBuilder("Product/Random/" + count);
  getData(uri)
    .then((data) => {
      return data;
    })
    .catch((error) => {
      throw new Error(error);
    });
  return null;
}
When it runs, I can see (via console.log) that data correctly has three products chosen at random. So far, so good.

So I try to call the service in one of my pages, like this:
JavaScript code:
import { useEffect, useState } from "react";
import { IProduct } from "../../Interfaces/IProduct";
import { RandomProducts } from "../../Services/ProductService";
import "./MainPage.css";

export default function MainPage() {
  const [products, setProducts] = useState<IProduct[] | null>(null);
  useEffect(() => {
    const p = RandomProducts(3);
    console.log("p = " + p);
    if (p) {
      setProducts(p);
    } else {
      setProducts(null!);
    }
  }, []);
  return (
    <div className="mainpage">
      <h1 className="mainwelcome">Welcome to the JimCo Retail site</h1>
      <h3 className="mainheader">Items selected for you!</h3>
      {products && <div>Products</div>}
      {!products && <p className="noproducts">No products were found</p>}
    </div>
  );
}
This does NOT work. The console.log shows that p is null (note that the "guts" of the page have not been fleshed out yet).

So I suspect that I have some sort of fundamental disconnect on promises or something. I can't figure out why RandomProducts has three products in an array, and seems to return it, but the caller is getting back null.

Can someone educate me please? TIA

camoseven
Dec 30, 2005

RODOLPHONE RINGIN'

LongSack posted:

I am in the middle of rewriting one of my Blazor server front ends into React. I don't think this is a React question, but more JavaScript related, so here goes.

I am making a retail store page as a demo (it also has an employee portal and vendor portal). On the index page, just for variety, the page selects three products at random and displays them to the user as items specially selected for them.

I have this function:
JavaScript code:
export function getData(url: string) {
  return fetch(url).then((response) => {
    if (!response.ok) {
      throw Error("There was an error fetching data: " + response.statusText);
    }
    return response.json();
  });
}
which works just fine. But rather than call getData all over the place, I'm trying to write services which abstract out the details. To that end, I've written my first service, ProductService which contains this function:
JavaScript code:
import { getData } from "./api";
import { IProduct } from "../Interfaces/IProduct";
import { uriBuilder } from "./tools";

export function RandomProducts(count: number): IProduct[] | null {
  const uri = uriBuilder("Product/Random/" + count);
  getData(uri)
    .then((data) => {
      return data;
    })
    .catch((error) => {
      throw new Error(error);
    });
  return null;
}
When it runs, I can see (via console.log) that data correctly has three products chosen at random. So far, so good.

So I try to call the service in one of my pages, like this:
JavaScript code:
import { useEffect, useState } from "react";
import { IProduct } from "../../Interfaces/IProduct";
import { RandomProducts } from "../../Services/ProductService";
import "./MainPage.css";

export default function MainPage() {
  const [products, setProducts] = useState<IProduct[] | null>(null);
  useEffect(() => {
    const p = RandomProducts(3);
    console.log("p = " + p);
    if (p) {
      setProducts(p);
    } else {
      setProducts(null!);
    }
  }, []);
  return (
    <div className="mainpage">
      <h1 className="mainwelcome">Welcome to the JimCo Retail site</h1>
      <h3 className="mainheader">Items selected for you!</h3>
      {products && <div>Products</div>}
      {!products && <p className="noproducts">No products were found</p>}
    </div>
  );
}
This does NOT work. The console.log shows that p is null (note that the "guts" of the page have not been fleshed out yet).

So I suspect that I have some sort of fundamental disconnect on promises or something. I can't figure out why RandomProducts has three products in an array, and seems to return it, but the caller is getting back null.

Can someone educate me please? TIA

The promise is asynchronous, so basically you are saying "go fetch me three products and let me know when you're done and what they are". But the code doesn't stop and wait for the fetch to happen, it moves right on to the console.log, if block, etc. I assume when you logged out of RandomProducts you were doing it in the "then" block, so it waited til the call was done then logged the data you got back.

Also RandomProducts returns null but it actually needs to return a promise, then you can async/await or chain it or whatever.

Phone posting but hopefully that helps a bit

LongSack
Jan 17, 2003

camoseven posted:

The promise is asynchronous, so basically you are saying "go fetch me three products and let me know when you're done and what they are". But the code doesn't stop and wait for the fetch to happen, it moves right on to the console.log, if block, etc. I assume when you logged out of RandomProducts you were doing it in the "then" block, so it waited til the call was done then logged the data you got back.

Also RandomProducts returns null but it actually needs to return a promise, then you can async/await or chain it or whatever.

Phone posting but hopefully that helps a bit

Thank you!

I changed ProductService to:
JavaScript code:
import { getData } from "./api";
import { IProduct } from "../Interfaces/IProduct";
import { uriBuilder } from "./tools";

export function RandomProducts(count: number): Promise<IProduct[] | null> {
  const uri = uriBuilder("Product/Random/" + count);
  return getData(uri)
    .then((data) => {
      return data;
    })
    .catch((error) => {
      throw new Error(error);
    });
}
then invoked it with
JavaScript code:
  const [products, setProducts] = useState<IProduct[] | null>(null);
  useEffect(() => {
    RandomProducts(3).then((data) => {
      if (data) {
        setProducts(data);
      } else {
        setProducts(null);
      }
    });
  }, []);
and it's working.

Mr. Bubbles
Jul 19, 2012
code:
 {"assignments":[{"date":"2022-04-01","lName":"lastname","uId":"12345","uCode":"LName1","fName":"FName1 ","aName":"AsignmentName1","aId":"998"}]}
I'd like to filter the above data to get a specific element's contents based on searching for an assignment name.

For instance in SQL like terms, Select * FROM assignments WHERE aName = 'AssignmentName1'.

I'm sure this is simple but having trouble with methods for how to accomplish it.

teen phone cutie
Jun 18, 2012

last year i rewrote something awful from scratch because i hate myself
you're looking for .find()

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find

TypeScript code:
/* returns either an object or undefined if none found */
data.assignments.find((eachAssignment) => eachAssignment.aName === 'AssignmentName1')
or if you need more than 1, use .filter

TypeScript code:
/* returns an Array<object> */
data.assignments.filter((eachAssignment) => eachAssignment.aName === 'AssignmentName1' || eachAssignment.aName === 'AssignmentName2' )

teen phone cutie fucked around with this message at 21:20 on Apr 20, 2022

Mr. Bubbles
Jul 19, 2012

teen phone cutie posted:

you're looking for .find()

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find

TypeScript code:
/* returns either an object or undefined if none found */
data.assignments.find((eachAssignment) => eachAssignment.aName === 'AssignmentName1')
or if you need more than 1, use .filter

TypeScript code:
/* returns an Array<object> */
data.assignments.filter((eachAssignment) => eachAssignment.aName === 'AssignmentName1' || eachAssignment.aName === 'AssignmentName2' )

Perfect, that did it. Thanks

worms butthole guy
Jan 29, 2021

by Fluffdaddy
Hey all, i'm having the hardest time trying to think up the right way to search for this, but does anyone know of a library that lets you take a image, let's say of a house, and overlay data on top of it? Sort of like a mapping tool that allows custom markers but only on a image and not on a geolocation basis...if that makes sense.

Sab669
Sep 24, 2009

I've never used this, but https://recogito.github.io/annotorious/ looks like it might fit what you want.

I've used image annotation packages for a C# project a long time ago. Forget how it all works, but I recall it being pretty easy to just overlay text dynamically onto an image.

Sounds like you're trying to "stack" layers images on top of one another though rather than text? What exactly do you mean by "markers"

worms butthole guy
Jan 29, 2021

by Fluffdaddy
That seems like it will work. Essentially what i'm doing is trying to make a "floorplan" out of a image that shows open vacancies in rooms etc, but it retrieves the data from a database. I think this annotation might work for that though but if you know of a mapping software solution that would work too! :)

LongSack
Jan 17, 2003

Yet another “React related but really a JavaScript question”

The Book I used to learn React with ASP.Net Core defined components like this:
TypeScript code:
const FooPage = () => { … Code and TSX here … }
And I, for some reason, am more comfortable doing them like this:
TypeScript code:
export default function FooPage() { … Code and TSX here … }
Both work, and the only difference I can see is that the first version is imported within braces, and my version is not, e.g.,
TypeScript code:
import { FooPage } from ‘../FooPage/FooPage’;
Versus
TypeScript code:
import FooPage from ‘../../FooPage’;
So my question is, is one of those better than the other? Preferred over the other? Or is it just a matter of preference? The first one is a lambda, which is an anonymous function, right?

TIA

minato
Jun 7, 2004

cutty cain't hang, say 7-up.
Taco Defender

LongSack posted:

So my question is, is one of those better than the other?
"const <function definition> .... ; export { <function names> }" allows many functions to be defined and exported from the same file. "export default ..." is simply syntactic sugar that's useful when you only want to export 1 thing, and means you can type slightly fewer chars when importing it. Apart from that, I don't believe there's any functional difference.

"const foo = () => <function definition>" is not quite equivalent to "function foo(...)", as there are differences in the way they are executed. For example, see this MDN example which shows how "this" is interpreted in an arrow function.

Miss Broccoli
May 1, 2020

by Jeffrey of YOSPOS
Are the reactstrap docs wrong?

I'm trying to use a dropdown, and the code exactly copy pasted from the docs doesn't work, it doesn't do anything when I click it.

https://reactstrap.github.io/?path=/docs/components-dropdown--dropdown

JavaScript code:
import {Dropdown, DropdownToggle, DropdownMenu, DropdownItem}from "reactstrap"
import 'bootstrap/dist/css/bootstrap.min.css';
JavaScript code:

function VolcList (){
    const {loading,countries,error}=useCountries();

    if (loading){
        return (
            <p> loading</p>
        )       
    }

    if (error){
        return (
            <p> error: {error.message}</p>
        )       
    }

    return (
            <div>
                <Dropdown toggle={function noRefCheck(){}}>
                    <DropdownToggle caret>
                    Dropdown
                    </DropdownToggle>
                    <DropdownMenu>
                        <DropdownItem header>
                            Header
                        </DropdownItem>
                        <DropdownItem>
                            Some Action
                        </DropdownItem>
                    </DropdownMenu>
                </Dropdown>
            </div>
    )

}

HexiDave
Mar 20, 2009

Miss Broccoli posted:

Are the reactstrap docs wrong?

I'm trying to use a dropdown, and the code exactly copy pasted from the docs doesn't work, it doesn't do anything when I click it.

https://reactstrap.github.io/?path=/docs/components-dropdown--dropdown

JavaScript code:
import {Dropdown, DropdownToggle, DropdownMenu, DropdownItem}from "reactstrap"
import 'bootstrap/dist/css/bootstrap.min.css';
JavaScript code:

function VolcList (){
    const {loading,countries,error}=useCountries();

    if (loading){
        return (
            <p> loading</p>
        )       
    }

    if (error){
        return (
            <p> error: {error.message}</p>
        )       
    }

    return (
            <div>
                <Dropdown toggle={function noRefCheck(){}}>
                    <DropdownToggle caret>
                    Dropdown
                    </DropdownToggle>
                    <DropdownMenu>
                        <DropdownItem header>
                            Header
                        </DropdownItem>
                        <DropdownItem>
                            Some Action
                        </DropdownItem>
                    </DropdownMenu>
                </Dropdown>
            </div>
    )

}

Looks like the actual code for the example is here: https://github.com/reactstrap/reactstrap/blob/master/stories/examples/Dropdown.js

You need some state code to handle the toggle for the root <Dropdown>

worms butthole guy
Jan 29, 2021

by Fluffdaddy
Hey all, I have a quick question about React and APIs.

I am calling a API like this:
code:
function getAttractionInfo(ride){
  const rides = 'https://ommited.com/ns/?format=json&search=' + ride;
  const rideCall = axios.get(rides).then(response=>{
    return response.data[0];
  })

  return rideCall;
}
What its returning is this:

code:
Promise { <state>: "pending" }
&#8203;
<state>: "fulfilled"
&#8203;
<value>: Object { id: 19}
How do I destructure / fix this to give me the object?

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

worms butthole guy posted:

Hey all, I have a quick question about React and APIs.

I am calling a API like this:
code:
function getAttractionInfo(ride){
  const rides = 'https://ommited.com/ns/?format=json&search=' + ride;
  const rideCall = axios.get(rides).then(response=>{
    return response.data[0];
  })

  return rideCall;
}
What its returning is this:

code:
Promise { <state>: "pending" }
&#8203;
<state>: "fulfilled"
&#8203;
<value>: Object { id: 19}
How do I destructure / fix this to give me the object?

Use async / await to wait for the call to complete before getting the value and returning:

code:
async function getAttractionInfo(ride){
  const rides = 'https://ommited.com/ns/?format=json&search=' + ride;
  const rideCall = await  axios.get(rides).then(response=>{
    return response.data[0];
  })

  return rideCall;
}
This is just normal old JS and would be the same React or not btw.

worms butthole guy
Jan 29, 2021

by Fluffdaddy

Lumpy posted:

Use async / await to wait for the call to complete before getting the value and returning:

code:
async function getAttractionInfo(ride){
  const rides = 'https://ommited.com/ns/?format=json&search=' + ride;
  const rideCall = await  axios.get(rides).then(response=>{
    return response.data[0];
  })

  return rideCall;
}
This is just normal old JS and would be the same React or not btw.

So I tried that and it works inside the function but if I try to call that function and assign it to a variable, and then console log it I get the same thing :(

code:
Promise { <state>: "pending" }

lunar detritus
May 6, 2009


worms butthole guy posted:

Hey all, I have a quick question about React and APIs.

I am calling a API like this:
code:
function getAttractionInfo(ride){
  const rides = 'https://ommited.com/ns/?format=json&search=' + ride;
  const rideCall = axios.get(rides).then(response=>{
    return response.data[0];
  })

  return rideCall;
}
What its returning is this:

code:
Promise { <state>: "pending" }
&#8203;
<state>: "fulfilled"
&#8203;
<value>: Object { id: 19}
How do I destructure / fix this to give me the object?

whew, you need to look up how promises work or you'll suffer every time you need to work with them.

What you're returning there is still a promise, you need to either work inside a then

code:
getAttractionInfo(ride).then((rideCall) => {
  doSomethingWithRideCall(rideCall)
})
or use async/await

code:
async function myfunction() {
  const rideCall = await getAttractionInfo(ride);
  doSomethingWithRideCall(rideCall)
}
EDIT:

worms butthole guy posted:

So I tried that and it works inside the function but if I try to call that function and assign it to a variable, and then console log it I get the same thing :(

code:
Promise { <state>: "pending" }

You need to call the function with await if you want to settle the promise, there's no way to skip that step.

minato
Jun 7, 2004

cutty cain't hang, say 7-up.
Taco Defender
code:
const MyReactComponent = (props) => {
   const [isLoading, setIsLoading] = useState(false);
   const [data, setData] = useState(null);

  const getAttractionInfo = async (ride) => {
    const rides = 'https://ommited.com/ns/?format=json&search=' + ride;
    response = await axios.get(rides);
    return response.data[0];
  }

  const someClickHandler = async (event) => {
     setIsLoading(true);
     try {
        setData(await getAttractionInfo(event.target.value));
     } catch (err) {
        console.log("Oh noes an error");
     }
     setIsLoading(false);
  }

  return <button onClick={someClickHandler} value={props.ride}>Click me<button/>;
}
(^^ that code is off the top of my head and is meant to be illustrative, not exemplary)

Axios.get immediately returns a Promise, which is a placeholder for the actual result that will eventually arrive later (unless an error occurs). The Promise's state will initially be unfulfilled, and a few ms later it will be fulfilled.

Promises were invented to avoid unmaintainable source code, where chains of async actions would result in "trees" of result handling code. However Promises also had their own syntax issues (lots of .then() statements and sub-functions), so they got surpassed by the "async/await" syntax above, which adds some syntactic sugar over Promises to allow the developer to write async code in a fashion that looks very close to (imo much more readable) synchronous code. You still have to know what a Promise is, but you don't have to care about it as much.


e: My code probably has a bug there, I think I fixed it. "Async somefunction() { ... }" means that "somefunction" returns a Promise, and "result = await somefunction()" calls that function and "pauses" the runtime until the Promise is fulfilled. You can only call "result = await somefunction();" from within a function marked as async, which can kinda lead to source code adding async/await all over the place. You can mark an event handler as async and that's fine, because although it's supposed to return a Promise, the browser (which calls the handler) throws away the result so it doesn't matter that it's not a "true" async function.

minato fucked around with this message at 00:15 on May 5, 2022

worms butthole guy
Jan 29, 2021

by Fluffdaddy
Cool thank you all. I usually work with NextJS or PHP so I never really have to deal with data fetching except for in the componentDidMount.

Miss Broccoli
May 1, 2020

by Jeffrey of YOSPOS
The way I got taught to do it is with an effect hook. Is that incorrect? like so:

code:
function useQuery(id){
    const [loading, setLoading] = useState(true)
    const [data, setData] = useState([])
    const [error, setError] = useState (null)

    useEffect(() => {
        const url = (`urltemplate${id}`)

        fetch(url)
        .then ((res)=> {
            if ((res.status ==200)){
                return res
            }else{
                throw Error(`Request rejected with status ${res.status}`);
            }
        })
        .then(result => result.json())
        .then(data => {
            setData(data)
        })
        .catch ((e)=> {
            setError(e)
        })
        .finally(()=> {
            setLoading(false)
        })
        
    }, [ID]);

    return {loading, data,error}
}
then inside the parent element that calls this
code:
    const {loading,data,error}=useQuery(ID);
    if (loading){
        return <p>Loading</p>
    } 
    if (error){
        return <p>error</p>
    }
    return (<p>the stuff you want to render with the data from the api call</p>)

worms butthole guy
Jan 29, 2021

by Fluffdaddy
Yeah so maybe i'm not using React the right way or something lol.

Essentially what i'm trying to do is this:

1. Hit a outside API that gathers the list of attractions
2. Sort that API to filter out attractions I dont want.
3. Then pick a random attraction from this object.
4. Then send the result of this object to the API call from above
5. Use a mix of data from number 3 & 4 to display info


and to all of this once every five minutes

I tried messing with promises and such last night but I eventually got to a point where it was just constantly running the API call non stop. I know with NextJS I could do all of this stuff before it even gets the chance to load the page, but React seems to want to load everything all at once, so i'll get random errors of xyz not being available yet.

So I wonder a few things:
1. Is there something else I should use for this besides React? I'd perfer not to use NextJS again as I wanted to change it up. This will never be publically exposed.
2. Am I doing everything wrong using a mixture of useeffect and promises and instead should just make one function that has a huge chain of .thens?
3. I've been using functional react; I know class based react CAN grab all this data before page generation right?

Thanks for the help and all the stupid questions. I don't have my code on me otherwise i'd post it.

worms butthole guy
Jan 29, 2021

by Fluffdaddy
Okay sorry for the delay. Here's the code I have:

code:

const pickRan = (obj) => {

        var keys = Object.keys(obj);
        return obj[keys[ keys.length * Math.random() << 0]];
}

const reqAssets = async() => {
    const allRides = await fetch(mkwaitAPI).then(res=>res.json())
    const mkHours = await fetch(mkhoursAPI).then(res=>res.json());

    const ranRide = await pickRan(allRides.filter(e=>e.meta.type === "ATTRACTION"))

    let pickedRide = await fetch(rides + ranRide.name).then(res=>res.json());
    pickedRide = pickedRide[0];

    return pickedRide;
}


function App() {
    const [ride,setRide] = useState();
    const [newRide, setnewRide] = useState();

    useEffect(()=>{
            setRide(reqAssets());
    },[])

    if (!ride) return null;

    console.log('ride: ' + ride);
  return (
      <>
      </>
  );
}
So I know this ultimately lies in my "useEffect" and my state. Right now, that final console.log(ride + ride) just returns "ride: [object Promise]". The reqAssets function seems to work fine except it's not actually returning anything, which i'm not sure why because if I type on top of the return statement console.log(pickedRide) it'll work...ripping my hair off over this lol.

Thanks for all help

first move tengen
Dec 2, 2011

worms butthole guy posted:

Okay sorry for the delay. Here's the code I have:

So I know this ultimately lies in my "useEffect" and my state. Right now, that final console.log(ride + ride) just returns "ride: [object Promise]". The reqAssets function seems to work fine except it's not actually returning anything, which i'm not sure why because if I type on top of the return statement console.log(pickedRide) it'll work...ripping my hair off over this lol.

Thanks for all help

Maybe try this?
code:
    useEffect(async ()=>{
            const ride = await reqAssets();
            console.log(“should be fetched”, ride)
            setRide(ride);
    },[])
Edit: never mind, I see that you’re not allowed to make the useEffect function async, maybe try rewriting like they do here (the part before they turn it into a custom hook): https://levelup.gitconnected.com/react-hooks-gotchas-setstate-in-async-effects-d2fd84b02305?gi=81457085b75

first move tengen fucked around with this message at 14:53 on May 6, 2022

Roadie
Jun 30, 2013

worms butthole guy posted:

So I know this ultimately lies in my "useEffect" and my state. Right now, that final console.log(ride + ride) just returns "ride: [object Promise]". The reqAssets function seems to work fine except it's not actually returning anything, which i'm not sure why because if I type on top of the return statement console.log(pickedRide) it'll work...ripping my hair off over this lol.

Thanks for all help

JavaScript code:
    const [ride, setRide] = useState();

    useEffect(() => {
        reqAssets.then(value => setRide(value));
    }, [])
Your async function returns a promise, not an unwrapped value. You have to resolve it to get your value.

Sab669
Sep 24, 2009

Has anyone encountered this error before?

quote:

Failed to compile.

./node_modules/ngx-extended-pdf-viewer/fesm2015/ngx-extended-pdf-viewer.mjs 3936:15510-15522
Can't import the named export 'AsyncPipe' from non EcmaScript module (only default export is available)

I'm trying to install this library, I tried both their Recommended Way and got the above error. Then I tried their Angular CLI steps but as soon as I add the imports to my app.module.ts I get the above error.

I've googled around a bunch and I see lots of posts with similar errors but a different export, and all the solutions seem specific to the whatever library that specific post is about.

camoseven
Dec 30, 2005

RODOLPHONE RINGIN'

Sab669 posted:

Has anyone encountered this error before?

I'm trying to install this library, I tried both their Recommended Way and got the above error. Then I tried their Angular CLI steps but as soon as I add the imports to my app.module.ts I get the above error.

I've googled around a bunch and I see lots of posts with similar errors but a different export, and all the solutions seem specific to the whatever library that specific post is about.

You need to set your bundler (probably webpack) to interpret .mjs files as js files. Or use an older version of that library that doesn't use .mjs files

Sab669
Sep 24, 2009

Thanks, although I have no idea how to do that :v: Looking into it now, definitely seems like a problem for Monday though.

Adbot
ADBOT LOVES YOU

LongSack
Jan 17, 2003

first move tengen posted:

Maybe try this?
code:
    useEffect(async ()=>{
            const ride = await reqAssets();
            console.log(“should be fetched”, ride)
            setRide(ride);
    },[])
Edit: never mind, I see that you’re not allowed to make the useEffect function async, maybe try rewriting like they do here (the part before they turn it into a custom hook): https://levelup.gitconnected.com/react-hooks-gotchas-setstate-in-async-effects-d2fd84b02305?gi=81457085b75

The way I handle this (thanks to “ASP.NET Core 5 and React Second Edition”) is like this:
TypeScript code:
useEffect(() => {
  async function doGetFoos() { … }
  doGetFoos();
}, []);
So create an async function inside the useEffect and then call that function.

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