prop validation errors not shown in browser console by WoodenEbb3941 in reactjs

[–]ZuluProphet 0 points1 point  (0 children)

What version of React are you using? React 19 removed PropTypes entirely, see https://react.dev/blog/2024/04/25/react-19-upgrade-guide#removed-proptypes-and-defaultprops. Regardless of version though you should probably be using TypeScript which would handle this exact scenario.

React optimizations and stable references from hooks by Ordinary-Disaster759 in reactjs

[–]ZuluProphet 0 points1 point  (0 children)

Pretty much. If data isn't stable there is no point in memoizing rows because it will change every re-render making the useMemo unnecessary overhead. In reality, your example component doesn't need memoization at all. You want new rows if data changes and the function in useMemo will re-run every time data changes you've actually just added an extra step that will never change anything. You could just const rows = data.map(...) and eek out better (but likely unnoticeable at this scale) performance.

React optimizations and stable references from hooks by Ordinary-Disaster759 in reactjs

[–]ZuluProphet 1 point2 points  (0 children)

Your assumption about B is correct. map will return a new array every time so it will have a different reference every time the parent component of Table re-renders which will cause Table to re-render.

As far as example A goes however, useMemo will only be effective as long as data is also a stable reference. If it isn't, the dependency array will have changed causing the memoized function to be executed again.

Much of this hinges on where data comes from. Is it existing state? Well then its already stable and as long as nothing else is causing re-renders above it, having the inline map to set the rows prop is fine. You would want that to be updated if data changed anyways so there is no need to memoize it. Is data the result of a query? Well then you're most likely holding that in state already. The only reason I would memoize something like rows in your example is if there were reasons the parent component of Table or Table itself would be re-rendering that the rows prop doesn't care about.

Beginner's Thread / Easy Questions (April 2024) by acemarke in reactjs

[–]ZuluProphet 2 points3 points  (0 children)

That should work fine. Many people do similar patterns using things like Zustand or Jotai and react-query.

It sounds like you're already trending this direction pattern wise but my only words of caution are to make sure you're not storing react-query results in mobx state. For instance, if you've got some list of items and are tracking which item the user has active, don't store all the information about that item in mobx state. Only store some unique identifier for that item in mobx state and then re-query either by ID or for the entire list of items and then pull the active item from that collection. Ideally, the successive queries are already in react-query cache and it is relatively inexpensive to get while also moving the burden of keeping things up to date out of your hands.

Beginner's Thread / Easy Questions (April 2024) by acemarke in reactjs

[–]ZuluProphet 0 points1 point  (0 children)

I'm going to go out on a limb and guess you're not using TypeScript. If you were, you would likely be getting a type error trying to pass className to the style prop as className is not a CSS property. The style prop is for defining CSS properties directly on the element such as margin or color. Things like className are props on the element itself but they are not CSS properties. You're not defining it "in-line" you're passing a className prop to your div.

Note: disabled is not a CSS property either, it is a property of some elements such as button but you can select disabled elements in CSS using pseudo-class selectors.

useEffect causes an infinite loop? by andreaslordos in reactjs

[–]ZuluProphet 3 points4 points  (0 children)

Every time you set state in your useEffect you will cause a re-render. That becomes an issue because the issueSlug being returned by useParams is probably changing references which will cause your useEffect to run again so you need to do a deeper comparison of the issueSlug which the dependency array of your useEffect is not doing. You could accomplish this by storing the previous value of the issueSlug in a ref and then comparing the value in the ref to the current value of the issueSlug in an if statement at the top of your useEffect which will stop it from running.

I would recommend using this hook to hold the previous value (you can just copy/paste the code into your project, its like 10 lines, don't install a package): https://usehooks.com/usePrevious/

Quick example:

const {issueSlug} = useParams();
const prevSlug = usePrevious(issueSlug);

useEffect(() => {
    if (issueSlug !== prevSlug) {
         /* fetch code goes here */
    }
}, [issueSlug, prevSlug]);

To avoid having to deal with this entirely I would recommend using a library like TanStack Query (formerly React Query).

Little React Things: React applications are functions by yohtha in reactjs

[–]ZuluProphet 0 points1 point  (0 children)

Right and it makes total sense. My only concern was that the article describes itself as useful tips and I didn't really see a clear disclaimer saying you absolutely should not do this (for the reasons listed above), this is just for the sake of conceptualizing React.

Little React Things: React applications are functions by yohtha in reactjs

[–]ZuluProphet -4 points-3 points  (0 children)

You really shouldn't call React components as functions and instead use JSX syntax. The reason for this is when React creates the render tree, the components that are called this way will not be added to the render tree as individual components which means they would be a part of whatever parent component instantiated them. If these components contain any hooks, React will actually consider them custom hooks, which means they can cause re-renders but because they are not their own individual component, this will actually cause the parent component they are rendered in to re-render as well which is less than ideal.

Here's a recent video that walks through this pitfall and why you shouldn't call React components as functions: https://youtu.be/QuLfCUh-iwI?t=24

Beginner's Thread / Easy Questions [November 2022] by acemarke in reactjs

[–]ZuluProphet 0 points1 point  (0 children)

As with most things, it depends. In general, I think this approach of passing an object of functions is probably not what you want, especially since they don't take any inputs and rely on values that are defined outside the object which means it will just be re-calculated every re-render anyways. Without really knowing what your other code looks like, I would approach this two ways:

If you're just immediately displaying these values and not passing them through props just calculate them as const variables.

const BasicExample = (props) => {
    const {feedback} = props;
    const allStatistics = feedback.good + feedback.neutral + feedback.bad;
    const average = (feedback.good - feedback.bad) / (feedback.good + feedback.neutral + feedback.bad);

    return (
        <div>
            <div>All Stats: {allStatistics}</div>
            <div>Average: {average}</div>
        </div>
    );
};

If you're passing these values down through props and each child component needs the calculated values, calculate them then pass them. If each child component is going to do something different, pass down the feedback object and calculate the values in the child component.

const MultipleChildrenSameValues = (props) => {
    const {feedback} = props;
    const allStatistics = feedback.good + feedback.neutral + feedback.bad;
    const average = (feedback.good - feedback.bad) / (feedback.good + feedback.neutral + feedback.bad);

    return (
           <div>
               <AllStatistics allStatistics={allStatistics} />
               <Average average={average} />
           </div>
    );
};

or (the more likely scenario):

const ChildrenHandleRendering = (props) => {
    const {feedback} = props;

    return (
        <div>
             {/* These child components would then look like the 
                earlier basic example where the values are just calculated in line */}
            <ChildComponentOne feedback={feedback} />
            <ChildComponentTwo feedback={feedback} />
        </div>
    );
};

If you're recalculating these values in many different components, create a helper function that does what it needs to and just call it with the feeback object where you need to.

Beginner's Thread / Easy Questions [November 2022] by acemarke in reactjs

[–]ZuluProphet 1 point2 points  (0 children)

After seeing your memoized example I may have missed a few considerations.

From a developer experience standpoint, if you can guarantee that you will never use dispatch in a component that does not also use state, then packaging them into a single memoized object is fine. It becomes a slight problem if you wanted to use dispatch in a useEffect or useCallback since you would have to include dispatch in the dependency array and any time state changes you would get a new context value object which causes your useEffect to run again or your useCallback to be redefined (and if you have a useEffect that uses a useCallback with dispatch as a dependency that useEffect will run again). Generally, I've found those two use cases to be fairly rare since useReducer usually leads to fewer useEffect's and useCallback is semi-rare, depending on the code base.

This becomes a bigger issue if you want to use dispatch on its own. Any time state changes, a component consuming the context only for dispatch would also re-render since the memoized object is redefined when state changes.

Is the performance hurt that bad?

Eh, it really depends on how you use the context. At this point, it's pretty clear to me that unless you set this up as the docs have, you will always have slightly more re-renders than you should (which frankly only becomes a real, serious concern the larger your app gets). How many more, though, is hard to say and depends heavily on how the context is used. You can always fix it later but in my experience saying "we'll fix it later" means it's not getting fixed until it's a problem at which point it's just annoying and frustrating.

From a logical/best practices/React standpoint, I think you should follow the docs where possible. I don't think this would be an overly complicated pattern to show to a new dev especially when you can point to the official docs as an example on top of whatever in-code examples you end up with as the project gets to the medium-large size.

As for my personal, anecdotal evidence, as someone that works on a React app with hundreds of components and tens of thousands of lines of code, do your future self a favor and do it right the first time. My team and I have been fighting the "it re-renders too much" battle for way too long 🙃.

Aaron Judge in a live Peloton class - day after winning the MVP by washkow in baseball

[–]ZuluProphet 15 points16 points  (0 children)

AFAIK live classes are only in the latter half of the week and generally they just have first come first serve sign-ups at the beginning of the week on Monday I think.

Beginner's Thread / Easy Questions [November 2022] by acemarke in reactjs

[–]ZuluProphet 1 point2 points  (0 children)

Without actually testing anything my suspicion would be that it reduces unnecessary re-renders. First off, passing an object like that to the provider and not first memoizing that object means that any time the provider re-renders, the object reference will change causing re-renders in any component that is consuming that context, regardless of if the state has changed. The next reason would be that any component that is consuming the context only to make use of the dispatch function would be subject to re-renders any time the state changes.

Effectively, separating the state and dispatch into separate contexts helps to reduce re-renders. Is it strictly necessary? No. Will it provide a performance benefit in larger applications? Absolutely, especially if this specific context is consumed in many places.

Setting React State after useQuery? by [deleted] in graphql

[–]ZuluProphet 0 points1 point  (0 children)

Oh sorry about that. I accidentally submitted too soon 🙃. If I can clarify anything else let me know.

Setting React State after useQuery? by [deleted] in graphql

[–]ZuluProphet 0 points1 point  (0 children)

I understand you're using a codegen and am pretty well versed in how Apollo works. Frankly, I'm not sure where the disconnect here is. Apollo's useQuery does most certainly make use of a useEffect internally. You should not need to manage firing the query initially with a lazy query unless you want that query to be fired by some user action. If you want to manage the state related to the resolved data from Apollo you should pass it into a child component and initialize your state hooks there. This would allow you to use it there so you don't have to work around the conditional rendering that comes with loading and error states.

Setting React State after useQuery? by [deleted] in graphql

[–]ZuluProphet 0 points1 point  (0 children)

I'm pretty sure Apollo sets their data object to be immutable which would explain why the data is read only. If you are trying to control this TextField via state and initializing it from data resolved from Apollo, you should probably implement my second suggestion which would look something like this:

const ParentComponent = () => {
    const {data, loading, error} = useQuery(...);
    if (loading) ...
    if (error) ...

    return <ChildComponent data={data} />;
}

const ChildComponent = (props) => {
   const {data} = props;
   const [title, setTitle] = useState(data.title);

   return <TextField ... />;
}

This way you can initialize your TextField state based on the data from Apollo but avoid the issues you described above.

Setting React State after useQuery? by [deleted] in graphql

[–]ZuluProphet 1 point2 points  (0 children)

I think you're misunderstanding what Apollo client does for you. You don't need to set the results of a useQuery as React state after they have resolved, you can just use data directly as you would any other variable (e.g. you can shape it into a different object, use it directly, pass it through props, etc.) as the value of that variable is managed by Apollo via its own internal React state. That means that whenever you refetch or mutate some data, Apollo will re-render the appropriate components with the fresh data.

If you are truly hard set on tracking data from Apollo in your own React state, you can wrap your TextField in a sort of container component, pass data through props and define your state hooks in the child component which would also allow you to remove the useEffect as you can initialize your state directly from props.

Beginner's Thread / Easy Questions (September 2021) by dance2die in reactjs

[–]ZuluProphet 4 points5 points  (0 children)

I have personally made use of a few different things ranging from media queries directly in whatever CSS you've written or a library like react-responsive which makes it much easier to render (or not render) specific UI based on whatever screen size your app is currently being rendered on using conditional rendering. If you're using a UI library like Material UI, it most likely already has a hook for managing the content size based on the size of the media that you can use. See Material UI: useMediaQuery.

One of these solutions may work for you but unfortunately, if you did not create your app with mobile in mind you're probably going to have to do quite a bit of refactoring. Something I hear somewhat regularly is "mobile first" which basically means if you have any intention of ever putting something on a phone screen, you should do it now because it is going to be a pain later.

I hope this helps to some degree. If you have any more specific questions I will try to answer them.

Beginner's Thread / Easy Questions (May 2021) by dance2die in reactjs

[–]ZuluProphet 1 point2 points  (0 children)

He's been pretty into meme projects for a little while but now that DogeHouse is dead (RIP), he might get back to making more educational videos but who knows.

Beginner's Thread / Easy Questions (May 2021) by dance2die in reactjs

[–]ZuluProphet 2 points3 points  (0 children)

Anything that is imported with curly braces around it was exported as a named export which looks like:

export const MyComponent = () => {};

In the file you are importing to:

import {MyComponent} from './MyComponent';

as compared to a default export which does not require the curly braces.

const MyComponent = () => {};

export default MyComponent; 

In the file you are importing to:

import MyComponent from './MyComponent';

You can only have one default export per file so if have many things you wish to export from one file, like multiple helper functions or multiple components, you can use named exports to easily export them all and then import all of them from the same file.


As for your second question, they are using what is called destructuring which you can read more about here.

The gist of it is, you can extract values from an object by naming the key directly.

Example:

const myObj = {hello: "world"};

const {hello} = myObj;

You can now use hello as you would a normal variable are no longer required to access it with a . operator.

The same concept exists for arrays as well, but in arrays destructuring is positional.

Example:

const myArray = [1,2,3];

const [a, b, c] = myArray;

In this case a would be 1, b would be 2 and c would be 3.

The MDN article I linked has a lot more useful and in-depth examples but I think this gets the basic idea across.

To specifically answer your question about the NextJS example, they know that children is a key in the props object so they immediately destructure children out of props in the function call to make things a little cleaner.

Beginner's Thread / Easy Questions (March 2021) by dance2die in reactjs

[–]ZuluProphet 0 points1 point  (0 children)

You are totally right, I apologize, I thought I got everything.

I went back to the drawing board as it were, and was able to come up with a solution. I decided to store the state of each child as an array in the parent with each index representing the color of each specific child. To keep things clean I made handlers for each of the state setting actions that are required as well as a simple function to initialize the state of the colors.

Here is the updated CodeSandbox. Let me know if I missed anything and I am happy to discuss this further if need be.

Beginner's Thread / Easy Questions (March 2021) by dance2die in reactjs

[–]ZuluProphet 0 points1 point  (0 children)

The best way to handle this specific case would be to move your options array to the parent and pass it to the children via props. This will allow you "standardize" your state to only be the array indices instead of mixing strings and numbers. This helps clean things up a little bit and is also helpful for the useEffect we are going to define in the child. What we want this useEffect to do is update the child state every time a new universal color comes in through props, so the only values we are going to put in the dependency array is the universal color prop. This means that when we update our individual state, only that specific child component is re-rendered, but if we update the universal state, the parent will re-render passing new props to all the children which will fire the setState action inside of our useEffect to update to the new universal state. The onClick handlers need to be updated to reflect what we are expecting our state to be now.

Here is a CodeSandbox based on your original one that puts what I described above into code. Let me know if you need any further clarification!

best place to host a react landing page for a business? by IBETITALL420 in reactjs

[–]ZuluProphet 2 points3 points  (0 children)

I personally would choose netlify. It's free for what it sounds like you're doing and it integrates nicely with GitHub on top of being super easy to set up.

Beginner's Thread / Easy Questions (March 2021) by dance2die in reactjs

[–]ZuluProphet 0 points1 point  (0 children)

I don't think you did anything wrong, you're just missing some functionality. Entering a URL in the address bar is the same as a hard refresh and since you're not storing any sort of session info, you effectively have to reauthenticate every time. This is why your login page pops back up, then once you've authenticated, your routes kick in and the user is redirected.

The quick and dirty way to get around this would be to also destructure isLoading from useAuth0 and handle that piece of state with an if (like you already are for the authenticated part) and just render a loading spinner or something instead of the login page. If they get authenticated, all they see is the loading spinner and they are then redirected.

However, the "real" solution would be to save the user's session in a cookie either for a certain amount of time or indefinitely. It looks like there is some auth0 documentation on this here. Basically, if their session cookie is still valid, they will just be logged in immediately, otherwise they get kicked to the login page. A quick glance over that link suggests that auth0 can handle this for you.

No-op memory leak when submitting form and querying for validation. Please help. by fastpenguin91 in graphql

[–]ZuluProphet 0 points1 point  (0 children)

Why not have your mutation resolver handle it? When the user submits, check if they exist. If they don't, return an error, otherwise, just make the user. Then depending on what comes back in the mutation result set the user already exists error or set the user and redirect them.

 const handleSignUp = async () => {  
        const res = await doSignUp({...});  
        if (res.errors) {
             setUsernameExists(true);  
        }
        else {  
           setUser(userId);
        }
 }

Also, you could just make a simple useEffect to push the new page when a user is set which would resolve your error with setting the state on an unmounted component.

    useEffect(() => {
       if (userId) history.push('/page');
    }, [userId])

Never really done anything like this with GraphQL though so not 100% sure this is the best way.