Component Nesting in React
export default function ParentComponent(props) {
function InnerComponent() {
// ...
}
return (
<>
<InnerComponent />
</>
);
}
As you can see, InnerComponent
is inside ParentComponent
–this is component nesting. This may seem convenient to code, but it has some problems
- you can’t export
InnerComponent
&ParentComponent
is lesser re-usable. - Performance issue–
InnerComponent
will be recreated on each render ofParentComponent
You can create a seperate module for InnerComponent
or just write it outside ParentComponent
function InnerComponent(props) {
return (
// ...
);
}
export default function ComponentTwo(props) {
return (
<>
<InnerComponent />
</>
);
}
How to render HTML inside react?
You can use dangerouslySetInnerHTML
prop to render HTML in React. It is used to set HTML directly from React. You should be careful while using this property as it can cause XSS attacks.
what could be the reasons for unnecessary re-renders in react?
Unnecessary re-renders in components can occur due to several reasons, and it’s important to optimize your code to minimize them for better performance.
Here are some common reasons for unnecessary re-renders in functional components:
- Using inline functions in JSX props: If you pass an inline function as a prop to child components, those components will get re-rendered every time the parent component re-renders. This is because a new function is created on every render. You can optimize this by using
useCallback
hook to memoize the function. - Using
useState
hook with objects: If you useuseState
hook with objects, you need to make sure that you are not mutating the object. If you mutate the object, React will not be able to detect the change and will not re-render the component. You can optimize this by usinguseReducer
hook instead ofuseState
hook. - Using
useEffect
hook without dependencies: If you useuseEffect
hook without dependencies, it will run on every render. You can optimize this by passing an empty array as the second argument touseEffect
hook. - Parent Component Re-renders: If a parent component re-renders, all its child components will also re-render. You can optimize this by using
React.memo
to memoize the child component where possible. - Global State Changes: If you use global state management libraries like Redux, MobX, etc., and the global state changes, all the components that use that state will re-render. You can optimize this by using
useSelector
hook to select only the state that you need in a component. - Misusing Context: If you use Context API to pass data to child components, and the data changes, all the child components will re-render. You can optimize this by using
useContext
hook to select only the data that you need in a component.
You can also use React.StrictMode
to detect potential problems in your code that could cause unnecessary re-renders.
what is useTransition
hook
useTransition
hook allows you to mark certain updates as transitions so they can be deprioritized, allowing other, more urgent updates to be processed first. This ensures that the UI remains responsive during updates that might take some time.
import { useTransition, useState } from "react";
import { Posts } from "./Posts";
import { Home } from "./Home";
import { Contact } from "./Contact";
export function App() {
const [isPending, startTransition] = useTransition();
const [page, setPage] = useState("home");
function changePage(newPage: string) {
startTransition(() => {
setPage(newPage);
});
}
return (
<>
<button onClick={() => changePage("home")}>Home</button>
<button onClick={() => changePage("posts")}>Posts</button>
<button onClick={() => changePage("contact")}>Contact</button>
<hr />
{isPending && <div>Loading...</div>}
{page === "home" && <Home />}
{page === "posts" && <Posts />}
{page === "contact" && <Contact />}
</>
);
}
export function Home() {
return <div>Home</div>;
}
export function Contact() {
return <div>Contact</div>;
}
Posts component is artificially delayed by 500ms to emulate extremely slow code.
export function Posts() {
const items = [];
for (let i = 0; i < 500; i++) {
items.push(<SlowPost key={i} />);
}
return <ul>{items}</ul>;
}
function SlowPost() {
const startTime = performance.now();
while (performance.now() - startTime < 1) {
// Do nothing for 1 ms per item to emulate extremely slow code
}
return <li>Post</li>;
}
Now when you click on the Posts
button, you’ll notice that the UI remains responsive and you can still switch to other pages while the posts are loading. Try removing the startTransition
wrapper around setPage
in changePage
to see the difference.
What is the purpose of flushSync
in React?
The flushSync
function in React is used to flush updates synchronously. It schedules updates to be performed inside a high-priority task, ensuring that the updates are executed immediately and synchronously before returning control to the caller.
import { flushSync } from "react-dom";
flushSync(callback);
This is useful in situations where you need the DOM to be updated immediately, such as for measurements or to ensure synchronous rendering. However, excessive use of flushSync
can lead to degraded performance, so it should be used judiciously.
How to render React components as static HTML string?
The renderToString
function in React is part of the react-dom/server
package and is used to render React components on the server-side to a static HTML string. It is commonly used for server-side rendering (SSR) in React.
Can you use hooks in Server Components?
No, hooks are not supported in Server Components. Hooks are a client-side feature and are not supported in Server Components. However, you can use hooks in client components and import them into Server Components.
What is Hydration in React?
Hydration is the process of using client-side JavaScript to add interactivity to the markup generated by the server. When you use server-side rendering, the server returns a static HTML representation of the component tree. Once this reaches the browser, in order to make it interactive, React “hydrates” the static content, turning it into a fully interactive application.
How do you investigate a slow React app and identify performance bottlenecks?
There are many reasons why an app might be slow. It could be due to a slow network, a slow backend, or a slow client. It could also be due to a memory leak, unnecessary re-renders, or large bundle sizes.
Here are some tips to help you investigate and fix performance issues:
Use the React DevTools Profiler
The React DevTools Profiler helps you visualize how components render and identify costly renderings. It can also help you identify unnecessary re-renders.
Check for Unnecessary Renders
Ensure that components don’t render more often than needed. Be clear about the useEffect
dependencies and avoid creating new objects or arrays every render, as these can trigger unnecessary child component renders. Tools like why-did-you-render can help spot unnecessary re-renders.
Analyze Bundle Size
Use your production build to analyze your bundle size. Tools like webpack-bundle-analyzer or source-map-explorer can help you see if large libraries or unused code is slowing down the initial load.
Optimize Images & Assets
Ensure images are appropriately sized and use modern formats. Also, consider using CDNs for assets that don’t change often.
Lazy Load Components
Use lazy()
and dynamic imports to split your bundle and load components only when they’re needed. This can help reduce the initial load time.
Check Network Requests
Slow API calls or fetching large amounts of data can affect performance. Optimize your backend, paginate data, or cache results. You can also use tools like @tanstack/react-query or swr to help manage data fetching and caching.
Use Production Build for Testing
Ensure you’re testing the performance on a production build, as development builds are often slower due to extra checks and logs.
Regularly profiling and monitoring your app can help you spot and fix performance issues before they become significant problems. You can use tools like Lighthouse or Calibre to monitor your app’s performance over time.