The source code for this blog is available on GitHub.
Note
Top

What You Need to Know in React

Cover Image for What You Need to Know in React
Chen Han
Chen Han

What You Need to Know in React

React is a popular JavaScript library for building user interfaces, and it offers a range of powerful features and capabilities that can help you build efficient and effective web applications. Some of the key things you need to know in React include how to manage state and props, how to use the React lifecycle methods, and how to optimize performance using techniques like memoization and lazy loading. Additionally, there are a lot of caveats to be aware of when using advanced features like useEffect, useLayoutEffect, and the advanced usage of useMemo and useCallback, so it's important to understand the nuances of these functions and when to use them. By mastering the core concepts and features of React, you can become a proficient developer and build truly powerful and scalable applications.

useState Caveats

State updates might be async and batched, as they are in the context of an event handler. This provides better performance since it eliminates additional, unnecessary renders.

Use cases like the example you linked to should use the update function pattern: https://reactjs.org/docs/hooks-reference.html#functional-updates

This way multiple updates can accumulate (rather than override or conflict with each other).

Put another way:

const [state, setState] = useState({
  foo: "abc",
  bar: 123
});

// Do this!
setState(prevState => {
  return {
    ...prevState,
    foo: "def"
  };
});
setState(prevState => {
  return {
    ...prevState,
    bar: 456
  };
});

// Don't do this!
// It only works if setState is called synchronously (which is often not the case).
// Otherwise your change to "foo" will be overridden by the old "foo" value when you change "bar".
setState({
  ...state,
  foo: "def"
});
setState({
  ...state,
  bar: 456
});

You can refer to these 2 links to see the different usecase of the same concept. link1link2

What is useMemo used for the following code

const [cart, setCart] = useState(initialCart);

const providerValue = useMemo(
  () => ({
    cart,
    setCart,
  }),
  [cart]
);

In the code you provided, useMemo is being used to create a value that is based on the current value of the cart state variable, and to ensure that this value is only recalculated when the cart value changes.

useMemo is a hook in React that allows you to memoize the value of a function or expression. When you pass a function to useMemo, the hook will call the function and return the result, but it will only recalculate the result if one or more of the values in the second argument (the dependencies array) have changed. This can be useful for optimizing the performance of a component by avoiding unnecessary calculations.

In the code you provided, useMemo is being used to create an object that contains the current values of the cart and setCart variables. The object is passed to the providerValue variable, which is then used to provide the values to other components via a context provider. By using useMemo here, the object will only be recalculated if the cart value changes, which can help to avoid unnecessary re-renders of the component and its descendants.

I hope this helps! Let me know if you have any other questions.

Uncaught TypeError: destroy is not a function

The error "Uncaught TypeError: destroy is not a function" typically occurs when you are trying to call the destroy method on an object that does not have a destroy method. This error can occur in a Next.js application if you are trying to call destroy on an object that does not have this method, or if you are calling destroy on the wrong type of object.

To fix this error, you will need to identify the object that you are trying to call destroy on, and make sure that the object has a destroy method that you can call. You may also need to make sure that you are calling destroy at the appropriate time, and that you are passing any required arguments to the method.

For example, if you are using a third-party library that provides an object with a destroy method, you may need to check the documentation for the library to make sure that you are using the destroy method correctly. Alternatively, if you are trying to call destroy on an object that you have created yourself, you may need to make sure that you have implemented the destroy method correctly and that it is available on the object.

I hope this helps! Let me know if you have any other questions or if you need further assistance.

React will try to recreate this component tree from scratch using the error boundary you provided, ErrorBoundary.

An error boundary is a component in React that is used to catch and handle errors that occur during the rendering of a component or its descendants. When an error is caught by an error boundary, the component will be unmounted and replaced with a fallback component that you can specify.

In the case of the error you mentioned, "React will try to recreate this component tree from scratch using the error boundary you provided, ErrorBoundary," it sounds like you have an error boundary component called ErrorBoundary that is being used to catch an error that occurred during the rendering of a component tree. When this error occurs, React will attempt to recreate the component tree from scratch using the ErrorBoundary component as the root.

To fix this error, you will need to identify the cause of the error and find a way to prevent it from occurring. This may involve debugging the component tree and identifying any components that are causing the error, or it may involve updating your code to handle the error more gracefully. You can use the ErrorBoundary component to display a fallback UI or message to the user if the error occurs, or you can use the componentDidCatch lifecycle method to log the error and take other actions as needed.

I hope this helps! Let me know if you have any other questions or if you need further assistance.

Error: There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.

The error "There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering" typically occurs in a Next.js application when there is an error during the process of hydration, which is the process of taking the HTML and other data generated by the server-side rendering of a component and using it to create a fully interactive and functional client-side version of the component.

There are a few possible causes for this error:

  1. An error occurred during the rendering of the component on the server, which caused the server-side rendering to fail.
  2. An error occurred during the hydration process on the client, which caused the component to fail to render correctly.
  3. There is a mismatch between the initial HTML rendered on the server and the final HTML rendered on the client, which can cause the hydration process to fail.

To fix this error, you will need to identify the cause of the error and take the appropriate action to resolve it. This may involve debugging the component tree and identifying any components that are causing the error, or it may involve updating your code to handle the error more gracefully. You can use the ErrorBoundary component to display a fallback UI or message to the user if the error occurs, or you can use the componentDidCatch lifecycle method to log the error and take other actions as needed.

I hope this helps! Let me know if you have any other questions or if you need further assistance.

Suspense cannot handle the circumstance of mismatching between the initial HTML rendered on the server and the final HTML rendered on the client

If you are encountering a mismatch between the initial HTML rendered on the server and the final HTML rendered on the client, it is possible that the Suspense component may not be able to help you fix the error. The Suspense component is designed to handle errors that occur while a component is being rendered, and it allows you to specify a fallback component that will be displayed while the wrapped component is being rendered. However, it is not designed to handle errors that occur due to a mismatch between the initial HTML rendered on the server and the final HTML rendered on the client.

To fix this type of error, you will need to identify the cause of the mismatch and take the appropriate action to resolve it. This may involve debugging the component tree and identifying any components that are causing the error, or it may involve updating your code to ensure that the initial HTML rendered on the server is consistent with the final HTML rendered on the client.

One possible cause of this error is that the server-side rendering of a component is generating different HTML than the client-side rendering of the same component. This can occur if the component is using state or props that are different between the server and the client, or if there are differences in the environment or context in which the component is being rendered.

To fix this error, you will need to ensure that the component is being rendered consistently on the server and the client, and that the initial HTML rendered on the server is consistent with the final HTML rendered on the client. You may also need to update your code to handle any differences in state or props between the server and the client, or to handle any other differences in the rendering environment or context.

How can I deal with Uncaught Error: There was an error while hydrating this Suspense boundary. Switched to client rendering.

Error: This Suspense boundary received an update before it finished hydrating. This caused the boundary to switch to client rendering. The usual way to fix this is to wrap the original update in startTransition.

SOLUTION: Using Next-Themes. This is not a React bug, but the Developer's.

After some further debugging, I have found a solution to my situation. My darkMode looked like this previously:

import { useTheme } from 'next-themes';

const ToggleButton: React.FunctionComponent = () => {
  const { theme, setTheme } = useTheme();
  return (
    <div className="flex items-center justify-center">
      <button
        type="button"
        aria-label="Light and Dark Mode Toggle Button"
        className="inline-flex items-center px-3 py-2 shadow-sm text-xs font-medium rounded dark:bg-white bg-slate-800 hover:scale-110 duration-500"
        onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}
      >
        {theme === 'light' ? '☀️' : '🌙'}
      </button>
    </div>
  );
};
export default ToggleButton;

I was receiving the following errors: Error: Hydration failed because the initial UI does not match what was rendered on the server. _next-dev.js?3515:25 Warning: Text content did not match. Server: "🌙" Client: "☀️"_ Uncaught Error: There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root

Here's a little on how Hydration works with the client/server: https://blog.saeloun.com/2021/12/16/hydration.html

This is the clarification provided on Next-Themes:

Warning! The above code is hydration unsafe and will throw a hydration mismatch warning when rendering with SSG or SSR. This is because we cannot know the theme on the server, so it will always be undefined until mounted on the client.

You should delay rendering any theme toggling UI until mounted on the client. See the [example](https://www.npmjs.com/package/next-themes?activeTab=readme#avoid-hydration-mismatch).

To fix this, make sure you only render UI that uses the current theme when the page is mounted on the client.

SOLUTION: After reviewing how React SSR Hydration works, my solution was this:

import { useTheme } from 'next-themes';
import { useState, useEffect } from 'react';

const ToggleButton: React.FunctionComponent = () => {
  const [mounted, setMounted] = useState(false);
  const { theme, setTheme } = useTheme();

  useEffect(() => setMounted(true), []);
  if (!mounted) return null;

  return (
    <div className="flex items-center justify-center">
      <button
        type="button"
        aria-label="Light and Dark Mode Toggle Button"
        className="inline-flex items-center px-3 py-2 shadow-sm text-xs font-medium rounded bg-white hover:scale-110 duration-500"
        onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
      >
        {theme === 'light' ? '☀️' : '🌙'}
      </button>
    </div>
  );
};

export default ToggleButton;

Immediate renders

Immediately after the very first render, we set some state, which immediately triggers a re-render. This has a performance cost, but it's necessary. Some developers try to get around this "double-render" by using a ref instead of state, to check whether they're on the server in the first render:

const SomeClientSideOnlyComponent = () => {
  const isRenderingOnServer = typeof window === 'undefined';
  // 🙅‍♀️ Don't do this:
  if (isRenderingOnServer) {
    return null;
  }
  return <div>Client only!</div>
};

This is a bad idea; it can lead to really wonky bugs.

const SomeClientSideOnlyComponent = () => {
  const hasMounted = useHasMounted();
  if (!hasMounted) {
    return null;
  }
  return <div>Client only!</div>
};

Suspense

Whenever you are creating a component that has dynamic data. Try importing that component in below mentioned format. It disables SSR and lets you render new data on API call.

import dynamic from 'next/dynamic'
const Table = dynamic(() => import("/design-systems/Molecules/Table"), { ssr: false });

forwardRef

We cannot prop ref in react. We can use forwardRef instead.

How to use forwardRef: https://blog.logrocket.com/complete-guide-react-refs/ The above example is how we change quantity in the checkout part.

Warning: forwardRef render functions accept exactly two parameters: props and ref. Did you forget to use the ref parameter?

Because of the warning, I change from function Input({ register, column, required, label, size, disabled, errors, searchIcon, ...rest }) to function Input(props, ref)

There is an error when mounting an onChange in regular input field because of the react-hook-form.
if ref exist &amp; need onchange to give track of the change
© 2024 WOOTHINK. All Rights Reserved.
Site MapTerms and ConditionsPrivacy PolicyCookie Policy