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
fuf
Sep 12, 2004

haha
I'm making a simple little media browser in Node (didn't there used to be a Node thread?).

I want to walk through my Movies directory and get all the file names:
code:
var fs = require('fs');

fs.readdir('/media/Movies', function(err, data) {
    // do stuff
});
But, if a movie is in its own sub-directory, I just wanna get the name of the biggest file in that directory (i.e. the actual movie), and nothing else. Any pointers?

Adbot
ADBOT LOVES YOU

fuf
Sep 12, 2004

haha

stoops posted:

I don't know much javascript or jquery. I mean, I can modify and get things to work, but i'm not comfortable writing it from scratch.

Does anyone have any great solid teaching resources? I don't mind paying for video tutorials, or online classes.

I can't seem to find any community college scripting programs, and i figured the net is the best way to go about it.

if any are highly recommended, I'd appreciate.

I really like this one:
http://eloquentjavascript.net/

fuf
Sep 12, 2004

haha
Is this the right place for obscure Node questions?

I need to watch a directory for new files, including files that might be in a subdirectory.

I've tried 3 modules:
https://github.com/mikeal/watch
https://github.com/yuanchuan/node-watch
https://github.com/bevry/watchr

but they all have the same problem: if I copy a directory that contains a file into the watch folder, they only pick up on the "new directory" event, and ignore the file.

If I create the directory first, then copy the file into it, both events get picked up fine. But I need to copy folders that already contain files into my watch directory and have them all picked up at once.

Any ideas? Is this the kind of thing that I should raise an issue about on github? (kinda scared because I've never done that)

Or should I give up on the modules and write my own "walker" function that gets called periodically?

fuf
Sep 12, 2004

haha
Oh hey I guess I could.

I kept hesitating between whether to use a "watcher" or a "walker", but I guess what I could do is watch for new directories, then walk through them to get the files.

Life would be a lot easier if the watchers just picked up every actual change though.

Anyway thanks :)

fuf
Sep 12, 2004

haha
Reading some documentation (for Sequelize) and it has this:
code:
   if (!!err) {
what's up with the two nots? Is that a thing?

fuf
Sep 12, 2004

haha
That makes sense, thanks.

fuf
Sep 12, 2004

haha
What's a good parallax scrolling plugin?

I've tried
https://github.com/Prinzhorn/skrollr (couldn't get scrolling to work on mobile)
and
https://github.com/markdalgleish/stellar.js (looks bad on mobile and is buggy)

fuf
Sep 12, 2004

haha
Do parallax background images really count as hijacking scroll behaviour?

They are kind of a design necessity at this point so I definitely need to come up with something.

fuf
Sep 12, 2004

haha
I wrote a little node script to read a file, do a search and replace, then write the file.

When I run it on my Mac and then open the newly written file in vim there's now an unnecessary carriage return ("^M" character) at the end of every line. I thought this was a DOS / Windows thing so I'm not sure why node is putting them there.

Is there any way to stop Node doing that?

fuf
Sep 12, 2004

haha
this jquery question might not make sense because I dunno wtf I'm doing but...

I have an ajax call that gets the contents of a simple html page:

JavaScript code:
 $.ajax({
               type: "GET",
               url: "/get-titles/",
               success: function(result){
                    console.log(result);
               }
          });
the result looks something like:

code:
<body>
<ul>
<li>title 1</li>
<li>title 2</li>
<li>title 3</li>
</ul>
</body>
I want to turn this into an array like ['title1', 'title2', 'title3']

With jquery I could do something like:
JavaScript code:
var titles = [];
$('li').each(function(){
        titles.push($(this).text());
    });
But like how do I run this jquery against the return of my ajax call? The html isn't actually in the DOM, it's just in that "result" object.

I basically want:
JavaScript code:
 
var titles = [];
$.ajax({
               type: "GET",
               url: "/get-titles/",
               success: function(result){
			$('li').each(function(){ // SOMEHOW MAGICALLY SELECT <li> ELEMENTS WITHIN result RATHER THAN MAIN PAGE
        			titles.push($(this).text());
    			});
               }
          });
Does that make any sense and is it possible?

EDIT: lol I think I was overthinking this a bit. I just had to load the result into a random hidden div and then do my thing on that:

JavaScript code:
var titles = [];
$.ajax({
               type: "GET",
               url: "/get-titles/",
               success: function(result){
			$('#holder').html(result);
			$('#holder li').each(function(){
        			titles.push($(this).text());
    			});
               }
          });
Oh well typing out the question helped me think it through :)

fuf fucked around with this message at 17:38 on Sep 27, 2021

fuf
Sep 12, 2004

haha
it's a random little project running completely locally so no real concerns about security or bad practice

is $.each totally out of date or something?

fuf
Sep 12, 2004

haha
I think this is a really easy question but anything to do with asynchronous programming and callbacks etc. still fries my brain to an embarrassing degree.

I want to crawl five pages of a website using the node "crawler" package. The url for page 2 comes from the content of page 1, and so on for pages 3-5, so I need to wait until I have the content of the preceding page before queuing up a crawl of the next page.

Really simplified version of the basic crawler:

JavaScript code:
var c = new Crawler();

function CrawlUrl(url){
   c.queue([{
      uri: url,
      callback: function(error, res, done){   
         var $ = res.$;
         let nextPageUrl = $('.nextPageUrl');
   }}])
}
I tried something like this but it doesn't work (it starts a crawl of page 2 but then never calls "HandleCallback" a second time):

JavaScript code:
var c = new Crawler();

function CrawlUrl(url){
   let count = 0;
   QueueCrawl();

   function QueueCrawl(){
         c.queue([{
            uri: url,
            callback: HandleCallback
         }])
      }

   function HandleCallback(error, res, done){
      var $ = res.$;
      url = $('.nextPageUrl');
      count++;
      if(count < 5){
         QueueCrawl();
      }
   }      
}
What's a good way to approach something like this?

edit: I did it with a promise:

JavaScript code:
var c = new Crawler();

async function CrawlUrl(url){
   let count = 0;
   for(var i=0;i<5;i++){
      await Crawl();
   }

   function Crawl(){
      return new Promise((resolve, reject) => {
            c.queue([{
               uri: url,
               callback: function(error, res, done){
                 var $ = res.$;
                 url = $('.nextPageUrl');
                 resolve();
                 done();
             }
         }])
      }
   }      
}
I also realised that my initial code probably would have worked but I was missing the done() which closes the crawler connection so it wasn't queuing up the next crawl properly.

fuf fucked around with this message at 13:34 on Sep 25, 2022

fuf
Sep 12, 2004

haha
Can a real programmer explain why this doesn't work and what I should do instead?

code:
function GetData() {
    API.getData(payload, function (data) {
      setData(data);
      if(continuous) {
        GetData();
      }
    });
  }
If "continuous" is true I want to immediately start a new API call when the old one finishes.

The above code works but if I change "continuous" to false it still keeps running. Like it always thinks that "continuous" is true once it starts running.

This is in a React app if that matters.

e: never mind, I figured something out using useEffect.

fuf fucked around with this message at 14:48 on Nov 9, 2022

fuf
Sep 12, 2004

haha
I might be misunderstanding because I'm new to React too but I think you just want to put your dropdown in a child component and call it from the parent. Then you can pass down any functions you want to the child.

In the render method of your parent component you would have something like:
code:
<MyDropdown handleChange={handleChange}/>

fuf
Sep 12, 2004

haha
why does everyone write functions like this now:

code:
const handleChange = (e) => {
    updateValue(e.target.value)
 }
instead of like this:
code:
function HandleChange(e){
  updateValue(e.target.value)
}
?

fuf
Sep 12, 2004

haha

go play outside Skyler posted:

if you put HandleChange in a callback context, "this" will refer to the callback context with version 2. With version 1, "this" will be implicitly captured and refer to whatever it was when the function was defined.

Thanks, I just about get this.


MrMoo posted:

usually the same people believe https://standardjs.com/ is actually real.

This looks kind of good? What's the issue?

fuf
Sep 12, 2004

haha
I have some Christmas blues reflecting on my current (non Javascript) dev job.

Are there any Javascript / React learning resources that people would particularly recommend? Something that will make me feel less like an impostor and possibly set me up for applying for some jobs?

There's a million different "courses" out there so any kind of "this helped me" endorsement would be appreciated.

fuf
Sep 12, 2004

haha

Armauk posted:

What are you using at your current job?

Uhhh an incredibly obscure platform / language that's only used by Universities called SITS ("Strategic Information Technology Systems"). It's a weird niche I fell into by accident that means a secure job but development that is straight out of the 90s.

I have a fair bit of web dev experience though so I'm definitely not starting from scratch with JS or anything. I'm firmly in 'intermediate' territory, just with a strong sense that I'm missing fundamentals and need to update my skills.

fuf
Sep 12, 2004

haha

marshalljim posted:

It's not like there's some magic bullet beyond putting in the hours.

Yeah but those hours can be spent more or less efficiently. There's a huge difference in the quality of pedagogical material. With software dev courses especially there's a lot of pretty bad teachers out there. Good teaching is a real skill and unfortunately it doesn't often coincide with good software engineering skill.

fuf fucked around with this message at 09:10 on Dec 21, 2022

fuf
Sep 12, 2004

haha
So in React I think you're supposed to pass down functions from the parent to the child component so that it can be called by the child:

JavaScript code:
function DeleteTag(tag){
...
}

<TagList DeleteTag={DeleteTag}/>

This is fine but is it still the best way when your component hierarchy gets pretty large? Like:

JavaScript code:
// parent.js
function DeleteTag(tag){
[...]
}

<TagList DeleteTag={DeleteTag}/>


// TagList.js
[...]
<SingleTag DeleteTag={DeleteTag}/>
[...]

// SingleTag.js
[...]
<DeleteButton DeleteTag={DeleteTag}/>
[...]
This gets pretty annoying, especially with TypeScript where you have to be super explicit about the Props being passed down to every component. It's a lot of work to pass down a function three or so levels just so that it can finally be called by <DeleteButton>.

Is there a way to just call DeleteTag() in parent.js from <DeleteButton> directly? Or is that somehow going against the whole React ethos?

Is this where I want a custom hook maybe? (I don't really know what they are)

fuf fucked around with this message at 13:49 on Jan 28, 2023

fuf
Sep 12, 2004

haha

smackfu posted:

Yes, that is a classic concern with React. “Prop drilling” is the common term if you want to Google. The solution has usually been to have some global state that your various level componentscan hook directly into. Redux was popular for a while, I think plain React context is the current choice?

Also don’t capitalize your functions unless they are components.

Edit: React docs link: https://beta.reactjs.org/learn/passing-data-deeply-with-context

fsif posted:

Zustand has kind of become the de facto standard over context, I think.

Thanks, that's really helpful.

I've seen Redux mentioned a lot, and now I finally understand why it's useful.

I'm gonna try and rewrite things to use React Context.

It's annoying how you have to do things the wrong way first to figure out why the right way is the right way.

fuf
Sep 12, 2004

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

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

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

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

fuf
Sep 12, 2004

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

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

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

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

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


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

fuf
Sep 12, 2004

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

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

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

fuf
Sep 12, 2004

haha

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

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

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

E: So does something like this make sense?

JavaScript code:
// useAddCategory.js

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

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

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

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

    const addCategory = useAddCategory();

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

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


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

fuf
Sep 12, 2004

haha

fuf posted:

I'm using React contexts rather than zustand

As my little adventures with React continue, I'm now trying to refactor some stuff to use zustand instead of context providers.

One thing I can't figure out is how to replace the parameters that I was passing to the context providers.

Like right now I have stuff like:
JavaScript code:
<TagContextProvider tags={tags}>
	<AddTag>
	<TagList>
</TagContextProvider>


// Somewhere else
<TagContextProvider tags={newTags}>
	<AddTag>
	<TagList>
</TagContextProvider>
So I can reuse the same components but pass them different bits of state data.

If I wanna replace <TagContextProvider> with a zustand "store", then what's a good way to reuse Components but with different state stores or different elements of the same store?

fuf
Sep 12, 2004

haha
Just to update on the above, the issue is covered in this thread:

https://github.com/pmndrs/zustand/issues/128

Weirdly, the solution is just to use React context providers to pass in a particular store to a component.

So it feels like I've come full circle. If I'm still using context providers then why would I use zustand rather than just storing the state directly in the context like I was before?

The motivation for moving to zustand was to try and avoid the issue where components using a context provider have to re-render every time anything in the context changes. I'm assuming that if the context contains a zustand store then all the components are going to re-render when the store changes? I haven't actually tested this so maybe not.

fuf
Sep 12, 2004

haha
Hmm ok thank you. It might be time to finally learn what memoize means.

Ima Computer posted:

If you have global state which doesn't need multiple instances, then you don't need to use a Context at all, since all consumers can share a direct import reference to the same instance of the store.

yeah I have a handle on this, and zustand is really good for that stuff.

But I thought I was being clever by making big chunks of the UI reusable, like the same interface but with different (state) data loaded in. And this is where it gets tricky because it doesn't know which store to use.


fuf fucked around with this message at 14:59 on Mar 8, 2023

fuf
Sep 12, 2004

haha
Here's a React state value/reference issue that I don't understand.

I have a zustand store that uses immer and looks kind of like:
JavaScript code:
export default create(
	immer((set) => ({
		tags: [],
		currentTag: null,

		setCurrentTag: (id) => {
	        	set((state) => {
		        	state.currentTag = state.tags.find((tag) => tag.id === id);
		        });
	      },
	}))
)
I assumed that after beting set, currentTag would be a reference to one of the tags in the array, i.e. they would be the same object. But instead currentTag is its own object, and updates to it don't affect the version in the array and vice versa.

How can I make currentTag a reference to an object in the array?

fuf
Sep 12, 2004

haha

Roadie posted:

Why do you care about them being the same object in the first place?

I have a component for updating a tag that uses currentTag from the zustand store, and also an "updateTag" option that takes a tag ID:

JavaScript code:
 const tag = useTagStore((state) => state.currentTag);
 const updateTag = useTagStore((state) => state.updateTag);
The issue is that updateTag updates the version of the tag in the array of tags (as it should), but because currentTag is a separate object, the component doesn't reflect the changes that have just been made so you still see the old values.

e: the workaround I came up with is to just store an ID in currentTag instead of an actual tag object, so now my update component looks like:

JavaScript code:
  // ID version
  const tagId = useTagStore((state) => state.currentTagId);
  useEffect(() => {
  if (tagId) {
     tag = tags.find((tag) => tag.id === tagId);
     }
  }, [tagId]);
but it feels way messier.

fuf fucked around with this message at 12:36 on Mar 13, 2023

fuf
Sep 12, 2004

haha
I've been having great fun with React and zustand making a little card-based game/app.

But I'm at the point now where if my list of cards gets long (around 200 or so) then the whole thing gets noticeably sluggish. So I'm entering a scary and confusing new world of performance optimisation.

I know that the first part is trying to prevent unnecessary re-renders, and I'm sort of getting to grips with that.

But there are also lots of times when my <CardList> component really does have to re-render its long list of <Card> components, and this is what's causing most of the slowdown.

Is there a way to wait for a component to render before displaying it? Or does that not make sense as a question? When I search for stuff to do with adding a "loading..." feature to components it's always to do with waiting for data to load rather than waiting for a bit of DOM to render.

I might also be misunderstanding the cause of the sluggishness. It might not be the actual rendering but something else going on (I'm sorting the list, and also using the "persist" zustand middleware to store it when it changes).

I'm trying to use the chrome Dev tools React profiler but it's pretty hard to interpret the results. Are there any other tools that might give some good insight into what's causing the slowdown?

fuf
Sep 12, 2004

haha
Thanks for the replies.

Jabor posted:

Why does your CardList need to re-render every single card? Is something about every single card being changed at the same time?

The individual cards are not changing, but the array of cards is changing because it is being sorted, and cards are being added and removed, etc. I assumed that if the array changed then it would need to re-render every individual card, but maybe not? Can components change position within the DOM without technically being re-rendered if their internal content is identical?

The main action is moving cards between the "Deck" and the "Hand".

I don't actually have separate arrays for Deck and Hand, just one big "cards" array and individual cards have a property called "inHand". Then a <DeckList> that filters for !inHand cards, and a <HandList> that does the opposite. Maybe this is a fundamental design flaw.

If I run the profiler and move a card from Deck to Hand then the result looks like this:


It's hard to interpret the results because all the listed times for individual components are really low so it must just be a cumulative problem of having to render ~200 cards. Also I'm using react-beautiful-dnd to make the cards draggable so there's a long hierarchy of <Draggable>, <Droppable> etc. components (could this be part of the performance issue?).

If I go to my <Card> components then under "Why did this render?" it says "The parent component rendered".

The parent component for my <Card> components (through a few layers of react-beautiful-dnd stuff) is my <Deck> component, which uses my card list like this:

JavaScript code:
const cards = useDeckStore((state) => state.cards);
If I look at "Why did this render" for <Deck> then it says "Hook 3 changed". Hook 3 is the cards array in my zustand store:




I think I need to change it so that <Deck> doesn't re-render every <Card> whenever the cards array changes? But I'm not sure how.

In <Deck>, the list of cards is generated like this:

JavaScript code:
{cards.map((card) => (
   <Card id={card.id}>
)}
And then the top of <Card> looks like this:
JavaScript code:
export default function Card({ id}) {
  const card = useDeckStore(
    useCallback(
      (state) => state.cards.find((card) => card.id === id),
      [id]
    )
  );
Now that I post it I'm kind of embarrassed because I'm not sure why I'm doing it this way (with the useCallback). I think I must have read somewhere that this was better for performance to pass in the ID as a prop and then get the card (like it would only re-render if the id prop changes) but tbh I don't really know how or why it's working and whether this might actually be part of the problem.

fuf
Sep 12, 2004

haha
yeah sorry, I was trying to cut my posted code down to the basics to save confusion, but I do indeed have a key.

The actual code from <Deck> is:
JavaScript code:
.map((card, index) => (
                    <DraggableCard key={card.id} id={card.id} index={index} />
                  ))
and <DraggableCard> contains:
JavaScript code:
import { Box } from "@mui/material";
import React from "react";
import { Draggable } from "react-beautiful-dnd";
import Card from "./Card";

export default function DraggableCard({id, index}) {
  return (
    <Draggable key={id} draggableId={id} index={index}>
      {(provided) => (
        <Box
          ref={provided.innerRef}
          {...provided.draggableProps}
          {...provided.dragHandleProps}
        >
          <Card id={id}/>
        </Box>
      )}
    </Draggable>
  );
}
Sorry for the confusion, it would be great if that were the actual solution.

fuf
Sep 12, 2004

haha

Roadie posted:

The render prop there means it's probably fully re-rendering the contents every time, key or not, because it's a "new" child. This is part of why you see the render prop pattern much less in new libraries than back when it was the new cool thing everyone loved.

Removing the drag and drop functionality and wrapping the <Card> component in "memo" has helped a lot with performance.


I'm pretty sure I've pinned down the remaining sluggishness to the fact that I'm using the "persist" middleware for zustand, which saves the state to localstorage on every change. I'm currently saving the cards array to localstorage just because it's simple and I can keep the whole app self-contained without worrying (yet) about saving / loading data via an API. But now that the cards array is pretty big the constant saving on every single change to any card is causing issues I think.

I need to either remove the middleware and come up with my own save/load feature, or I need to change the "persist" middleware so it only saves periodically, or at least doesn't save on every change.

fuf
Sep 12, 2004

haha
I feel like I'm missing something with state management in React, specifically with large arrays.

My app has a large (well, like 800 or so) array of "card" elements, with various properties that get toggled on a per-card basis.

The various state solutions I've tried (React's useState, zustand, and most recently preact signals) all treat state arrays as immutable, so if I want to change the "enabled" property of a single card, then instead of:

code:
card.enabled = false
I have to do something like:
code:
updateCard({
...card,
enabled: false
})

// updateCard.js
updateCard = (card) => {
  state.cards = state.cards.map((c) => {
    if (c.id === card.id) {
      return card;
    }
    return c;
  });
};
(there might be a better way of doing this, but the principle of having to replace the entire array with a new array after each update is the same).

Because of this approach, my app feels really sluggish. Even if most of the cards aren't rendered, there's still a noticeable delay when changing any property of a card because it has to update the entire array.

I know packages like immer can help with updating immutable arrays, but I'm assuming the performance issue will be the same.

I was super excited when I discovered https://github.com/luisherranz/deepsignal because it achieves the dream of making state arrays mutable. So I can just do:

code:
card.enabled = false
and it magically works. It's also incredibly performant.

The issue I faced with this approach is that I can no longer listen for changes to the array. With the standard immutable array approach I can do something like:
code:
  useEffect(() => {
    syncToDb()
  }, [state.cards]);
and this works because replacing the entire state.cards array triggers the useEffect.

But this doesn't work with deepsignal because it's not replacing the entire array. I ended up doing some really clunky stuff with periodically checking for changes to decide when to write to the database, rather than the preferred option of just writing when there are changes.

Is there a state management solution that lets you treat arrays as mutable but also lets you trigger an effect when any property of any member of the array changes? Or is that just trying to have my cake and eat it?

I don't mind immutable arrays if I could figure out a way to improve performance...

fuf
Sep 12, 2004

haha

Osmosisch posted:

keep the cards in an object keyed by id instead of an array

Oh interesting I've never seen that before. I have a lot of places where I'm doing cards.filter and cards.map etc. though, how would I do all that normal array stuff if cards is an object?

fuf
Sep 12, 2004

haha
Yeah you guys are right that the performance issue is because of re-renders rather than replacing the array as such. But it's related because if I'm rendering my array of cards and I update one card and it replaces the whole array (because it is immutable) then it has to re-render the whole list, which is slow. But with deepsignal I could update one card and it would magically only re-render that one card in the list and it was really fast. It was honestly the dream solution apart from this issue of not being able to run a useEffect to save to db when the array changes.

Ima Computer posted:

Using an object as a map is a significantly worse solution here though, especially if maintaining the order of items in the list is important. It also means you have to call Object.entries() on every render before you can iterate over the items, which is going to have higher rendering computation cost and memory usage in comparison to just using an array in the first place.

I'm glad I'm not the only one who thought this was a weird suggestion. I've never seen any mention of using objects instead of arrays for state in React.

Ima Computer posted:

This is a problem space that's solved pretty nicely by atomic state management libraries like Recoil and Jotai. The splitAtom utility from Jotai especially seems like it would be a good fit here.

Oh yeah that Jotai splitAtom thing does look very promising, thank you. I might give it a whirl.

fuf
Sep 12, 2004

haha

Osmosisch posted:

Oh no, it wasn't meant as a final solution, more as a way of checking whether the updating was the issue. Sorry if that wasn't clear.

Oh I see, no worries, thanks for the replies!

fuf
Sep 12, 2004

haha
I have a pretty simple React app that I made with create-react-app and want to host somewhere.

A lot of the stuff I'm looking at, like https://www.digitalocean.com/products/app-platform, assumes that you want to pull from a github repo and then run the build process on the production server itself, but I'm struggling to see why this is an advantage.

If I run "npm run build" locally then what I end up with in the /build folder is just a static site that I can host anywhere, right? It feels easier to just deploy that folder directly to a basic hosting server running nginx, or even a crappy shared hosting package, compared to a server running a node build process.

Is it weird / bad to have a second github repo just for the /build directory to push new builds to the hosting server?

Do hosting providers get pissed if you host an actual "app" rather than just another generic WordPress site? It's just serving a couple of mb of html, js, and css so I don't see why, but maybe I'm missing something.

I saw something about using S3 to server static sites but that seems like overkill for where I'm at. I dunno if there's a middle ground somewhere between S3 and an old school cPanel on a shared host setup?

Adbot
ADBOT LOVES YOU

fuf
Sep 12, 2004

haha

fuf posted:

Is it weird / bad to have a second github repo just for the /build directory to push new builds to the hosting server?

I did this with a new "build" branch instead and removed /build from .gitignore on this branch.

Then I created a new DigitalOcean App and pointed it at the /build directory of the build branch and it successfully detected it as a static site and deployed it. Pretty cool!

I haven't used DO for years and I kind of love it. It's like baby's first AWS. It's pretty powerful but generally very straightforward.

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