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
necrotic
Aug 2, 2005
I owe my brother big time for this!
fs is a node module, it won’t exist in browser environments.

Adbot
ADBOT LOVES YOU

worms butthole guy
Jan 29, 2021

by Fluffdaddy
Something like that's I'd still use WordPress as the backend cms using wpgraphql and then next as the front end if I don't want to bother with pho.

Tea Bone
Feb 18, 2011

I'm going for gasps.
I'm trying to use a webscoket library in a react App (specifically react-actioncable-provider), but I'm having some problems with the React life cycle in functional components.

I've got it working with classical components with something similar to this:

code:
class Widget extends React.component{

	constructor(...props){
		super(...props)
		this.state = {messages:[]}
	}

	handleReceived = (message)=>{
		const messages = this.state.messages
		messages.push(message)
		this.setState({messages:messages})
	}

	render() {
		return (
			{this.consumer || this.consumer = <ActionCableConsumer
				channel="WidgetChannel"
				onReceived={this.handleReceived}
			/>}
			<ul>
				{this.state.messages.map(m, <li key={m.id}>{m.body}</li>}
			</ul>
		)
	}
}
The above just listens for messages on the channel then appends them to the messages state.
If I don't include the
code:
this.consumer || this.consumer = ...
and just render the <ActionCableConsumer> straight away, the app reconnects to the sever after every re-render, the "this.consumer || this.consumer = ..." keeps it to one connection per page load.

I thought I would be able to replicate this in a functional component using a ref:

code:
function Widget(props){
	[messages, setMessages] = useState([])
	consumer = useRef(<ActionCableConsumer
				channel="WidgetChannel"
				onReceived={handleReceived}
			/>)

	const handleReceived = (message)=>{
		setMessages([...messages, message]
	}

	return(
		{consumer.current}
		<ul>
			{messages.map(m, <li key={m.id}>{m.body}</li>}
		</ul>
	)
}
The ref works to keep the connection to one per page load, but the problem is accessing 'messages' from within the onReceived function always returns an empty array (or whatever I set the initial state to be) and not the updated state.
I thought I would be able to get around this with useEffect with 'messages' as a dependency but that causes a new connection to the web socket after every time messages updates.

I don't think this is a react-action-cable-provider problem or even a web socket problem rather just me missing something about the component life cycle in react. I can deal with having the odd classical component if need be but I'd really like to keep everything as functional components if possible.

Tea Bone fucked around with this message at 14:14 on Jul 13, 2021

Tanners
Dec 13, 2011

woof

Tea Bone posted:

I'm trying to use a webscoket library in a react App (specifically react-actioncable-provider), but I'm having some problems with the React life cycle in functional components.

I've got it working with classical components with something similar to this:

code:
class Widget extends React.component{

	constructor(...props){
		super(...props)
		this.state = {messages:[]}
	}

	handleReceived = (message)=>{
		const messages = this.state.messages
		messages.push(message)
		this.setState({messages:messages})
	}

	render() {
		return (
			{this.consumer || this.consumer = <ActionCableConsumer
				channel="WidgetChannel"
				onReceived={this.handleReceived}
			/>}
			<ul>
				{this.state.messages.map(m, <li key={m.id}>{m.body}</li>}
			</ul>
		)
	}
}
The above just listens for messages on the channel then appends them to the messages state.
If I don't include the
code:
this.consumer || this.consumer = ...
and just render the <ActionCableConsumer> straight away, the app reconnects to the sever after every re-render, the "this.consumer || this.consumer = ..." keeps it to one connection per page load.

I thought I would be able to replicate this in a functional component using a ref:

code:
function Widget(props){
	[messages, setMessages] = useState([])
	consumer = useRef(<ActionCableConsumer
				channel="WidgetChannel"
				onReceived={this.handleReceived}
			/>)

	const handleReceived = (message)=>{
		setMessages([...messages, message]
	}

	return(
		{consumer.current}
		<ul>
			{messages.map(m, <li key={m.id}>{m.body}</li>}
		</ul>
	)
}
The ref works to keep the connection to one per page load, but the problem is accessing 'messages' from within the onReceived function always returns an empty array (or whatever I set the initial state to be) and not the updated state.
I thought I would be able to get around this with useEffect with 'messages' as a dependency but that causes a new connection to the web socket after every time messages updates.

I don't think this is a react-action-cable-provider problem or even a web socket problem rather just me missing something about the component life cycle in react. I can deal with having the odd classical component if need be but I'd really like to keep everything as functional components if possible.

Looks like you're passing this.handleRecieved still, but you changed that to a regular const, so you should just pass handleRecieved instead. Also, you may need to have the function declaration before the usage.

e: Also if you're just starting out it's probably not worth it yet, but as you get more comfortable Typescript can catch issues like this for you, and I highly recommend it.

Tea Bone
Feb 18, 2011

I'm going for gasps.
Ah sorry, no that's just from where I was copy and pasting in the post. In my app I do indeed just pass handleReceived.

I assume it's something to do with the handleReceived function using the messages state from when it was passed to the ActionCableConsumer component in the ref

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

Tea Bone posted:

Ah sorry, no that's just from where I was copy and pasting in the post. In my app I do indeed just pass handleReceived.

I assume it's something to do with the handleReceived function using the messages state from when it was passed to the ActionCableConsumer component in the ref

Correct, you are simply re-rendering the exact same "initial" component there there that is stored in the ref, which will never update.

That library is very old, and whole it may work now, it is using lots of deprecated syntax / lifecycle methods. Looks like there are open issue reports on that in the repo (https://github.com/cpunion/react-actioncable-provider/issues/27) and a fix someone submitted two years ago (https://github.com/cpunion/react-actioncable-provider/pull/26) that has not been merged, since the project looks abandoned.


If I were doing something like this, ActioncableConsumer would not be a component, but a hook, and my code would likely look akin to:

JavaScript code:
const MyThing = () => {
  // hold your messages
  const [msg, setMsg] = useState([]);
  const channel = "lolButtes";

  handleReceived = (m) => setMsg([...msg, m]);
  
  const { consumer } = useActioncableConsumer(channel, handleReceived);
  useEffect(() => consumer.disconnect, []);
 
  return (
   <ul>{message.map( ... )}</ul>
  );

}
That library seems pretty simple, so it would be pretty straightforward to write a hook based one, and it seems that someone has done just that: https://github.com/weilandia/use-action-cable#readme

Lumpy fucked around with this message at 16:33 on Jul 13, 2021

Tea Bone
Feb 18, 2011

I'm going for gasps.

Lumpy posted:

Correct, you are simply re-rendering the exact same "initial" component there there that is stored in the ref, which will never update.

That library is very old, and whole it may work now, it is using lots of deprecated syntax / lifecycle methods. Looks like there are open issue reports on that in the repo (https://github.com/cpunion/react-actioncable-provider/issues/27) and a fix someone submitted two years ago (https://github.com/cpunion/react-actioncable-provider/pull/26) that has not been merged, since the project looks abandoned.


If I were doing something like this, ActioncableConsumer would not be a component, but a hook, and my code would likely look akin to:

JavaScript code:
const MyThing = () => {
  // hold your messages
  const [msg, setMsg] = useState([]);
  const channel = "lolButtes";

  handleReceived = (m) => setMsg([...msg, m]);
  
  const { consumer } = useActioncableConsumer(channel, handleReceived);
  useEffect(() => consumer.disconnect, []);
 
  return (
   <ul>{message.map( ... )}</ul>
  );

}
That library seems pretty simple, so it would be pretty straightforward to write a hook based one, and it seems that someone has done just that: https://github.com/weilandia/use-action-cable#readme

This is great thanks. I figured at some point I'd need to ditch the library and implement my own, which I still might but this looks like it should simplify things for the time being.

LifeLynx
Feb 27, 2001

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

Fixins posted:

Something like that's I'd still use WordPress as the backend cms using wpgraphql and then next as the front end if I don't want to bother with pho.

Would you still do that if you weren't using a blog? Like is there a benefit to using WP to hold the HTML for the pages? Right now I don't even do that, I have a custom-built plugin in WP to load HTML into the main loop for pages, with WP itself just providing everything in the head tag. So the only people that really concern themselves with WP's backend are the SEO team who configures Yoast and all that.

UtahIsNotAState
Jun 27, 2006

Dick will make you slap somebody!

Tea Bone posted:

I'm trying to use a webscoket library in a react App (specifically react-actioncable-provider), but I'm having some problems with the React life cycle in functional components.

I've got it working with classical components with something similar to this:

code:
class Widget extends React.component{

	constructor(...props){
		super(...props)
		this.state = {messages:[]}
	}

	handleReceived = (message)=>{
		const messages = this.state.messages
		messages.push(message)
		this.setState({messages:messages})
	}

	render() {
		return (
			{this.consumer || this.consumer = <ActionCableConsumer
				channel="WidgetChannel"
				onReceived={this.handleReceived}
			/>}
			<ul>
				{this.state.messages.map(m, <li key={m.id}>{m.body}</li>}
			</ul>
		)
	}
}
The above just listens for messages on the channel then appends them to the messages state.
If I don't include the
code:
this.consumer || this.consumer = ...
and just render the <ActionCableConsumer> straight away, the app reconnects to the sever after every re-render, the "this.consumer || this.consumer = ..." keeps it to one connection per page load.

I thought I would be able to replicate this in a functional component using a ref:

code:
function Widget(props){
	[messages, setMessages] = useState([])
	consumer = useRef(<ActionCableConsumer
				channel="WidgetChannel"
				onReceived={handleReceived}
			/>)

	const handleReceived = (message)=>{
		setMessages([...messages, message]
	}

	return(
		{consumer.current}
		<ul>
			{messages.map(m, <li key={m.id}>{m.body}</li>}
		</ul>
	)
}
The ref works to keep the connection to one per page load, but the problem is accessing 'messages' from within the onReceived function always returns an empty array (or whatever I set the initial state to be) and not the updated state.
I thought I would be able to get around this with useEffect with 'messages' as a dependency but that causes a new connection to the web socket after every time messages updates.

I don't think this is a react-action-cable-provider problem or even a web socket problem rather just me missing something about the component life cycle in react. I can deal with having the odd classical component if need be but I'd really like to keep everything as functional components if possible.


Tea Bone posted:

This is great thanks. I figured at some point I'd need to ditch the library and implement my own, which I still might but this looks like it should simplify things for the time being.

I've been learning about useCallback and useMemo. If you are using a functional component, and you were having problems with re-rendering would that be a good use case for useMemo? Additionally for

code:
handleReceived = (m) => setMsg([...msg, m]);
 
would wrapping this with useCallback help as well?

To be clear:

1) I've never had to do anything remotely related to websockets so I don't know anything about writing code for it.

2) I've only started reading up on useCallback and useMemo the other day, so I was just wondering if that would apply in this case.

worms butthole guy
Jan 29, 2021

by Fluffdaddy

LifeLynx posted:

Would you still do that if you weren't using a blog? Like is there a benefit to using WP to hold the HTML for the pages? Right now I don't even do that, I have a custom-built plugin in WP to load HTML into the main loop for pages, with WP itself just providing everything in the head tag. So the only people that really concern themselves with WP's backend are the SEO team who configures Yoast and all that.

I've never really used it to hold HTML, instead I've used it for data management. So for example I have CPTUI and ACF installed on that WordPress and I use wpgraphql to expose that data and use it to dynamically make pages in nextjs. I guess it's still essentially a "blog" type website though.

https://search.nhlovescampers.com/camps?city=all&campfeatures=all&region=all&camptype=all

Here's the NextJS site I made that utilizes this to store the campgrounds and coordinates for the map. It seems to be working okay.

Tea Bone
Feb 18, 2011

I'm going for gasps.

UtahIsNotAState posted:

I've been learning about useCallback and useMemo. If you are using a functional component, and you were having problems with re-rendering would that be a good use case for useMemo? Additionally for

code:
handleReceived = (m) => setMsg([...msg, m]);
 
would wrapping this with useCallback help as well?

To be clear:

1) I've never had to do anything remotely related to websockets so I don't know anything about writing code for it.

2) I've only started reading up on useCallback and useMemo the other day, so I was just wondering if that would apply in this case.

Thanks, yeah I was thinking wrapping handleReceived in useCallback might be along the lines of what I want, with the messages as a dep, but I expect that will just cause the re-connection to happen since it will pass the function in as a new prop.

It's working exactly as needed in a classical component with:
code:
{this.consumer || this.consumer = <ActionCableConsumer .../>}
But I'm too novice to know exactly what that's doing and replicate on a stateful component.

Sous Videodrome
Apr 9, 2020

|| is or

so if the left hand this.consumer is defined already, it never looks at the right side of the or operator

if the left hand this.consumer is undefined, it looks at the right side of the or operator and performs the assignment operation.

So the first time it runs, this.consumer on the left side is undefined. It looks at the right side and performs the assignment operation, assigning the value of <ActionCableConsumer .../> to this.consumer.

On all other lifecycles of the component this.consumer is already defined (as <ActionCableConsumer .../>) so it doesn't do anything with the right side of the || operator.

If you wanted to do that on a functional component, I'd use useEffect

code:
const [ consumer, setConsumer] = useState(null)

  useEffect(() => {   
	setConsumer(<ActionCableConsumer />)  
}, 
//empty dependency array means it only executes once
// like the old componentDidMount
[]
);

Sous Videodrome fucked around with this message at 22:48 on Jul 20, 2021

Tea Bone
Feb 18, 2011

I'm going for gasps.
Yeah, moving it to useEffect was one of my first inclinations but that had the same problem where handleReceived would never access the updated state.

I get that the "||" is an "or" and what that's doing. What I don't understand is how "this.consumer" in a class component is scoped differently to putting the consumer in a state in a functional component which allows the class variant to access the updated sate in handleReceived.

It doesn't matter too much, as was suggested earlier I should probably switch to a newer library anyway but I'm just curious now what's going on under the hood.

Saoshyant
Oct 26, 2010

:hmmorks: :orks:


Anyone familiar with Angular? I was trying to help a student working with it and, boy howdy, am I not experienced with this framework enough to figure out what we are doing wrong here.

So, we get all content dynamically from a backend API. This works great up to a point. The main menu, for instance, is getting everything generated fine, but when we access the routerLink for a topic from this menu, on the first time it activates what's on ngOnInit and loads the data correctly (there's an Angular service call here, which gets the data from an Observable, which I gather is the correct way to do this), but after that, every other click on the menu does nothing even though the URL parameters change in the browser. ngOnInit is only called once and never again after the first click in the menu, even though we are accessing different pages in this route.

My assumption is that ngOnInit is not supposed to be used in this way, then. The Angular tutorials I found don't seem to point out what we should be doing instead though, and what few StackOverflow answers I found were people hacking and hammering things around this limitation.

Saoshyant fucked around with this message at 15:16 on Aug 3, 2021

The Merkinman
Apr 22, 2007

I sell only quality merkins. What is a merkin you ask? Why, it's a wig for your genitals!

Saoshyant posted:

Anyone familiar with Angular? I was trying to help a student working with it and, boy howdy, am I not experienced with this framework enough to figure out what we are doing wrong here.

So, we get all content dynamically from a backend API. This works great up to a point. The main menu, for instance, is getting everything generated fine, but when we access the routerLink for a topic from this menu, on the first time it activates what's on ngOnInit and loads the data correctly (there's an Angular service call here, which gets the data from an Observable, which I gather is the correct way to do this), but after that, every other click on the menu does nothing even though the URL parameters change in the browser. ngOnInit is only called once and never again after the first click in the menu, even though we are accessing different pages in this route.

My assumption is that ngOnInit is not supposed to be used in this way, then. The Angular tutorials I found don't seem to point out what we should be doing instead though, and what few StackOverflow answers I found were people hacking and hammering things around this limitation.

You might have better luck in the Modern Front-end Development thread, but I'll put in my two cents.

If the URL parameters are changing, you need to subscribe to said changes. ngOnIt only fires once, so that's why no future clicks are doing anything. this should be a quick enough explanation. Whatever you want to happen when the menu is clicked, would go in place of the console.log(param)

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

Saoshyant posted:

Anyone familiar with Angular? I was trying to help a student working with it and, boy howdy, am I not experienced with this framework enough to figure out what we are doing wrong here.

So, we get all content dynamically from a backend API. This works great up to a point. The main menu, for instance, is getting everything generated fine, but when we access the routerLink for a topic from this menu, on the first time it activates what's on ngOnInit and loads the data correctly (there's an Angular service call here, which gets the data from an Observable, which I gather is the correct way to do this), but after that, every other click on the menu does nothing even though the URL parameters change in the browser. ngOnInit is only called once and never again after the first click in the menu, even though we are accessing different pages in this route.

My assumption is that ngOnInit is not supposed to be used in this way, then. The Angular tutorials I found don't seem to point out what we should be doing instead though, and what few StackOverflow answers I found were people hacking and hammering things around this limitation.

ngOnInit is only ever called once according to the docs. It looks like you're trying to respond to the routing data changing? I'm not quite clear what your desired behaviour is exactly. Please provide a bit more detail about the app structure, and what changes/actions you expect to propagate.

Maybe have a look here: https://ultimatecourses.com/blog/exploring-angular-lifecycle-hooks-onchanges

Saoshyant
Oct 26, 2010

:hmmorks: :orks:


Osmosisch posted:

ngOnInit is only ever called once according to the docs. It looks like you're trying to respond to the routing data changing? I'm not quite clear what your desired behaviour is exactly. Please provide a bit more detail about the app structure, and what changes/actions you expect to propagate.

The desired behavior is exactly what you described: responding to the routing data changing. There's a main menu being loaded in the app.component. That main menu routes to different components depending on what kind of subsection is listed, and every one of those components makes a call to a service (which calls a backend API to collect the data). Clicking once on a link like /dongs/Dong-1 works the first time, but if the user clicks on /dongs/Dong-2 nothing happens because the service call is in ngOnInit and it only fires once (and our unfamiliarity with the framework just got us as far as, "this is probably not the right way to do this").

I'll review the onchanges hooks stuff you linked and see if I can take it from here.

The Merkinman posted:

this should be a quick enough explanation.

Edit: actually, this may be right answer. That pipe/subscribe over the queryParamMap may be the missing piece of the puzzle on how this stuff should work. Gonna test it out.

Saoshyant fucked around with this message at 15:48 on Aug 3, 2021

The Merkinman
Apr 22, 2007

I sell only quality merkins. What is a merkin you ask? Why, it's a wig for your genitals!

Saoshyant posted:

The desired behavior is exactly what you described: responding to the routing data changing. There's a main menu being loaded in the app.component. That main menu routes to different components depending on what kind of subsection is listed, and every one of those components makes a call to a service (which calls a backend API to collect the data). Clicking once on a link like /dongs/Dong-1 works the first time, but if the user clicks on /dongs/Dong-2 nothing happens because the service call is in ngOnInit and it only fires once (and our unfamiliarity with the framework just got us as far as, "this is probably not the right way to do this").

I'll review the onchanges hooks stuff you linked and see if I can take it from here.

Edit: actually, this may be right answer. That pipe/subscribe over the queryParamMap may be the missing piece of the puzzle on how this stuff should work. Gonna test it out.

What I posted was for query parameters /?dong=1, /?dong=2. What you are showing, /dongs/Dong-1, /dongs/Dong-2 are route changes, which are different but similar

The Merkinman fucked around with this message at 18:03 on Aug 3, 2021

LifeLynx
Feb 27, 2001

Dang so this is like looking over his shoulder in real-time
Grimey Drawer
Alright, I'm trying to do this the React way and not seeing a good way to do it. In the non-React world, I've done things like this:

code:
<p data-anim="fade-in">This will fade in when it's in view.</p>
With an IntersectionObserver watching for the data-anim attribute and giving/taking away the classname specified with data-anim. I use querySelectorAll for this. In React, that's harder to do because of the virtual DOM, but I want to make it work the same way. I found [url="https://"""]react-intersection-observer[/url] but it's stumping me because it keeps only triggering if everything with useInView or InView is visible, which is very not what I want.

What I want is to be able to do something like this:

code:
<p data-anim="fade-in" className={ `is-page-height ${inView}` }>First Element</p>
<p data-anim="fade-in" className={ `is-page-height ${inView}` }>Second Element</p>
(For the sake of argument, .is-page-height is min-height: 110vh or something to make sure they're not both on the screen at the same time.)

Am I thinking about this the wrong way? It took me a while to accomplish my previous goal of getting WPGraphQL to cooperate, so my brain is mush.

EVIL Gibson
Mar 23, 2001

Internet of Things is just someone else's computer that people can't help attaching cameras and door locks to!
:vapes:
Switchblade Switcharoo
I recently got frustrated at the bullshit in Path of Exile where most English speaking players never reply to you when trading for low value items. Path of Exile does everything through a webpage. Here is my tampermonkey script to remove all English sellers from bulk item search.
code:
// ==UserScript==
// @name         Path of Exile gently caress English
// @namespace    [url]http://tampermonkey.net/[/url]
// @version      0.0.d3adb33f
// @description  Toggles visability of all English sellers
// @author       EVIL Gibson
// @match        [url]https://www.pathofexile.com/trade/exchange/*[/url]
// @require      [url]https://code.jquery.com/jquery-3.6.0.js[/url]
// @grant        window.onurlchange
// @grant        unsafeWindow
// @grant        GM_Log
// @grant        GM_Info
// @run-at       context-menu
// ==/UserScript==

(function() {

    var jQuery = window.jQuery;
    window.jQuery = window.$ = jQuery;
    $("div.row.exchange").find("img[alt='en_US']").parentsUntil("div.row.exchange").parent().toggle();
    var remove_eng = jQuery('.maincontent-wide')
   // GM_log("run!");
    GM_info;


    // Your code here...
})();
I saw that triple assignment of jquery somewhere and it works. Forgot to remove the var

For https://www.pathofexile.com/trade/exchange/Expedition

Before

After


This is the site where the page works. You need to select what currency you want and what currency/currencies you have. The api will be called and then render all the offers.

This script is very simple since there is a convenient img alternate text with "en_US" and I use Jquery to remove it.

Now to put where my experience is as a "developer", I am not a developer. I use javascript to attack iphone/android phones, find hidden "secrets" in application pentesting (the worst was some dev putting all the server u/p in a base64 string that had to be decoded), and write regex to automatically use javascript functions to expose "sensitive" actions.

What I haven't actually learned is programming good javascript.

Now the issue. The other half of the trade page.

https://www.pathofexile.com/trade/search/Expedition/dVKOIJ

The search for an "Astramentis" unique amulet looks like this.



The render does not include that convenient flag icon but it does include the "Whisper" button which, when clicked (and only when clicked), will copy to your clipboard a message in the user's language. This information is fetched from the DOM array that comes from one to many previous API calls (https://www.pathofexile.com/api/trade/fetch/[comma seperated list of first ten userIDs selling the item]?query=dVKOIJ[/u])


Writing a one liner script is basically impossible. I need to either a) read the JSON and link up that userId (which is a div with an attribute data-id of the users ID) so I know which to hide (or unhide) or b) run javascript as the CSS loads (which I don't know how to inject into running JS) and skip all rendering that has the id in function so I can check each as they load but that sounds it would slow down the site immensely.

For A, the issue would be there are many API calls depending how far down you scroll and the array could be giant. The B the issue would be my unfamiliarity with inserting the tampermonkey actions (or know which run-at would actually do this. documentation is... not very descriptive of this to me) as the javascript of the page runs.

What say you, masters of javascript?

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:

Alright, I'm trying to do this the React way and not seeing a good way to do it. In the non-React world, I've done things like this:

code:
<p data-anim="fade-in">This will fade in when it's in view.</p>
With an IntersectionObserver watching for the data-anim attribute and giving/taking away the classname specified with data-anim. I use querySelectorAll for this. In React, that's harder to do because of the virtual DOM, but I want to make it work the same way. I found [url="https://"""]react-intersection-observer[/url] but it's stumping me because it keeps only triggering if everything with useInView or InView is visible, which is very not what I want.

What I want is to be able to do something like this:

code:
<p data-anim="fade-in" className={ `is-page-height ${inView}` }>First Element</p>
<p data-anim="fade-in" className={ `is-page-height ${inView}` }>Second Element</p>
(For the sake of argument, .is-page-height is min-height: 110vh or something to make sure they're not both on the screen at the same time.)

Am I thinking about this the wrong way? It took me a while to accomplish my previous goal of getting WPGraphQL to cooperate, so my brain is mush.

Maybe throw up a fiddle/codepen with the minimal attempt you describe above? In general setting classes and other properties via react isn't an issue, and the hook listed in the package you linked should do what you want.

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

LifeLynx posted:

Alright, I'm trying to do this the React way and not seeing a good way to do it. In the non-React world, I've done things like this:

code:
<p data-anim="fade-in">This will fade in when it's in view.</p>
With an IntersectionObserver watching for the data-anim attribute and giving/taking away the classname specified with data-anim. I use querySelectorAll for this. In React, that's harder to do because of the virtual DOM, but I want to make it work the same way. I found [url="https://"""]react-intersection-observer[/url] but it's stumping me because it keeps only triggering if everything with useInView or InView is visible, which is very not what I want.

What I want is to be able to do something like this:

code:
<p data-anim="fade-in" className={ `is-page-height ${inView}` }>First Element</p>
<p data-anim="fade-in" className={ `is-page-height ${inView}` }>Second Element</p>
(For the sake of argument, .is-page-height is min-height: 110vh or something to make sure they're not both on the screen at the same time.)

Am I thinking about this the wrong way? It took me a while to accomplish my previous goal of getting WPGraphQL to cooperate, so my brain is mush.

This does not directly answer your question, but I do things like this using react-hook-inview:

JavaScript code:
import { useInView } from 'react-hook-inview';

const SomeComponent= (props) => {
  const [ref, isVisible] = useInView({
    threshold: 0.25,
    rootMargin: "120px",
    unobserveOnEnter: true,  // so we only trigger once
  });
  return (
    <div ref={ref} className={ isVisible ? "animateMe" : "hideMeOrWhatever" }>
     { props.children }
    </div>
  );
  /*
    ALTERNATELY: 
    return (
       <div ref={ref} >
        <p className={ isVisible ? "animateMe" : "hideMeOrWhatever" }> Something</p>
        <p className={ isVisible ? "animateMe" : "hideMeOrWhatever" }> Another Thing</p>
      </div>
)
    (but this would animate both P at the same time) Just wrap each P in "SomeComponent" to do them seperately)
  */
}
So if you aren't tied to the library you are using, maybe give that a whirl.

Lumpy fucked around with this message at 21:53 on Aug 5, 2021

LifeLynx
Feb 27, 2001

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

Lumpy posted:

This does not directly answer your question, but I do things like this using react-hook-inview:

JavaScript code:
import { useInView } from 'react-hook-inview';

const SomeComponent= (props) => {
  const [ref, isVisible] = useInView({
    threshold: 0.25,
    rootMargin: "120px",
    unobserveOnEnter: true,  // so we only trigger once
  });
  return (
    <div ref={ref} className={ isVisible ? "animateMe" : "hideMeOrWhatever" }>
     { props.children }
    </div>
  );
  /*
    ALTERNATELY: 
    return (
       <div ref={ref} >
        <p className={ isVisible ? "animateMe" : "hideMeOrWhatever" }> Something</p>
        <p className={ isVisible ? "animateMe" : "hideMeOrWhatever" }> Another Thing</p>
      </div>
)
    (but this would animate both P at the same time) Just wrap each P in "SomeComponent" to do them seperately)
  */
}
So if you aren't tied to the library you are using, maybe give that a whirl.

Thanks for sharing, it made me see something similar between react-intersection-observer and react-hook-inview. I think I'm supposed to wrap each element I want to animate in a component, or use a component for each element. RIO has a "use as" feature, like InView as="section". I'm wondering if I'd need to do that instead of trying to simply toggle a class on an existing element, because of the way React handles state? Maybe isVisible doesn't update for each component, just everything with ref={ref} as a whole? I admit I'm not up to date with the whole state stuff.

Munkeymon
Aug 14, 2003

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



EVIL Gibson posted:

For A, the issue would be there are many API calls depending how far down you scroll and the array could be giant. The B the issue would be my unfamiliarity with inserting the tampermonkey actions (or know which run-at would actually do this. documentation is... not very descriptive of this to me) as the javascript of the page runs.

Just try A and prevent your script from hammering the API too hard by caching IDs in localStorage or sessionStorage (if you're worried the players will change languages often) IMO

Tunicate
May 15, 2012

Is there a way to beep the PC speaker via javascript?

Dancer
May 23, 2011

Tunicate posted:

Is there a way to beep the PC speaker via javascript?

Begone, demon!

Impotence
Nov 8, 2010
Lipstick Apathy

Tunicate posted:

Is there a way to beep the PC speaker via javascript?

What do you mean by a PC speaker? I don't think you can tell if someone is using speakers or headphones.

You can use <audio> to play a beep.

gbut
Mar 28, 2008

😤I put the UN🇺🇳 in 🎊FUN🎉


Tunicate posted:

Is there a way to beep the PC speaker via javascript?

JavaScript code:
console.log('\u0007');

gbut
Mar 28, 2008

😤I put the UN🇺🇳 in 🎊FUN🎉


Biowarfare posted:

What do you mean by a PC speaker? I don't think you can tell if someone is using speakers or headphones.

You can use <audio> to play a beep.

I think he's referring to that obsolete little pulse signal driven speaker in old PCs that just beeps, or produces harsh 1-bit noise if you really want to have a go at it.

Impotence
Nov 8, 2010
Lipstick Apathy

gbut posted:

I think he's referring to that obsolete little pulse signal driven speaker in old PCs that just beeps, or produces harsh 1-bit noise if you really want to have a go at it.

I have not experienced this, who builds a speaker into the computer itself? Laptops? I know some VMs I have will play some sounds on boot but they play via the regular audio stack.

gbut
Mar 28, 2008

😤I put the UN🇺🇳 in 🎊FUN🎉


Biowarfare posted:

I have not experienced this, who builds a speaker into the computer itself? Laptops? I know some VMs I have will play some sounds on boot but they play via the regular audio stack.

In the olden times, all IBM Compatibles (TM) came with a built in beeper (a piezzo speaker usually) that would beep the boot error codes and such. If you had a sound card, and maybe a CD rom drive, it would have been a Multimedia PC (TM) but those were expensive and rare early on.

There's a package for doing beeps, but I doubt anyone bothers maintaining something that would allow you to send custom signals via node.
https://www.npmjs.com/package/node-beep

E: the speaker was not necesarily limited to PC compats. Even earlier systems used ASCII "bell" (code 7 I posted above) that would produce audible "warning". On macs it was replaced by that default "boink" sound coming from the sound card. I haven't touched PC hardware internals in a decade or so, but I believe motherboards should come with a tiny piezzo speaker for the boot issue signaling, as it would be useful when stuff goes sideways.

gbut fucked around with this message at 21:43 on Aug 6, 2021

Impotence
Nov 8, 2010
Lipstick Apathy
now my question becomes how is anything that legacy and historical even capable of running modern javascript

gbut
Mar 28, 2008

😤I put the UN🇺🇳 in 🎊FUN🎉


It's still all higher or lower voltage that gets interpreted as ones and zeroes, when you look deep enough. Even your node/browser code. Just like ENIAC and the like.

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

LifeLynx posted:

Thanks for sharing, it made me see something similar between react-intersection-observer and react-hook-inview. I think I'm supposed to wrap each element I want to animate in a component, or use a component for each element. RIO has a "use as" feature, like InView as="section". I'm wondering if I'd need to do that instead of trying to simply toggle a class on an existing element, because of the way React handles state? Maybe isVisible doesn't update for each component, just everything with ref={ref} as a whole? I admit I'm not up to date with the whole state stuff.

I took a quick look at their docs, and if you want each component to animate on it's own when coming into view (by changing the class name) you can do it via hooks in every individual component if they need different classes applied:

JavaScript code:
import { useInView } from 'react-intersection-observer';

const ComponentA = () => {
 const { ref, inView } = useInView();
 return (
  <div ref={ref} className={ inView ? 'visibleClass' : 'notVisisble'}> farts </div>
 );
}

const ComponentB = () => {
 const { ref, inView } = useInView();
 return (
  <div ref={ref} className={ inView ? 'otherVisibleClass' : 'otherNotVisisble'}> buttes </div>
 );
}
or you can create a single wrapper if the class will be the same on all:

JavaScript code:
import { useInView } from 'react-intersection-observer';

const Animator = (props) => {
 const { ref, inView } = useInView();
 return (
  <div ref={ref} className={ inView ? 'visibleClass' : 'notVisisble'}>
    { props.children}
  </div>
 );
}
// elsewhere...
<Animator> farts </Animator>
<Animator> buttes </Animator>
You could also add a prop to your Animator component that takes the visible and not visible class names to make it usable for all cases.


You can also do the same stuff inline using their InView component which uses the (yucky, in my opinion) render prop pattern:

JavaScript code:
import { InView } from 'react-intersection-observer';

const SomeBigComponent = () => {

return (
<section>
<h1>omg look at this</h1>
<p>these don't do anything fancy, but below here will!</p>
 <InView>
    {({ inView, ref, entry }) => (
      <div ref={ref} className={ inView ? 'visibleClass' : 'notVisisble'}>
        <h2>farts</h2>
      </div>
    )}
  </InView>
  <InView>
    {({ inView, ref, entry }) => (
      <div ref={ref} className={ inView ? 'visibleClass' : 'notVisisble'}>
        <h2>buttes</h2>
      </div>
    )}
    </InView>
    <p>I won't do anything fancy though.</p>
  </section>
  );
}

Tunicate
May 15, 2012

gbut posted:

I think he's referring to that obsolete little pulse signal driven speaker in old PCs that just beeps, or produces harsh 1-bit noise if you really want to have a go at it.

Yeah the one that's used for beep codes at boot. Usually built into the motherboard nowadays but I just kept calling it the PC speaker

lunar detritus
May 6, 2009


Biowarfare posted:

I have not experienced this, who builds a speaker into the computer itself? Laptops? I know some VMs I have will play some sounds on boot but they play via the regular audio stack.

thanks for making me feel old, jerk

Ola
Jul 19, 2004

That reminded me of the pinball games which had amazing sound quality for PC speaker.

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

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

Munkeymon
Aug 14, 2003

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



Biowarfare posted:

I have not experienced this, who builds a speaker into the computer itself? Laptops? I know some VMs I have will play some sounds on boot but they play via the regular audio stack.



This is from the manual of a reasonably new motherboard - X570 chipset, so probably came out about a year ago. It's still there, but a lot of people won't hook it up, partially because it could usually still make noise even if the OS volume was muted.

HappyHippo
Nov 19, 2003
Do you have an Air Miles Card?

Biowarfare posted:

now my question becomes how is anything that legacy and historical even capable of running modern javascript

My computer beeps when I turn it on and manages to run javascript

Adbot
ADBOT LOVES YOU

gbut
Mar 28, 2008

😤I put the UN🇺🇳 in 🎊FUN🎉


This thread is making me consider writing a floppy drive rattle node package.

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