Skip to main content

Featured Post

AIforce Is Now SIforce: What Salesforce Renamed and What It Means

SIforce is the new name for AIforce , Salesforce's agentic integration layer. CEO Marc Benioff announced the rename on X on October 9, 2026, writing: "The era of Super Intelligence is here. AIForce is officially SIForce." If you searched for "what products were renamed from AIforce to SIforce", the short answer is one : AIforce itself. This guide explains what changed, what did not, and what it means for admins and developers. Quick Answer: What Was Renamed? Earlier name Current name Date Headless 360 (became AIforce) April 2026 – September 2026 AIforce (became SIforce) September 15, 2026 – October 9, 2026 SIforce Current name October 9, 2026 – present That makes SIforce the third name for the same feature in just over six months. As of the coverage we reviewed, no other Salesforce product was reported as renamed from "AI" to "SI". Agentforce, Einstein and the other Salesforce products were not mentioned in the rename reports. W...

Top 5 React.js Performance Optimization Techniques (React 19)

React applications rarely start slow. They get slow gradually — a context provider here, an unmemoized list there — until someone opens the Profiler and finds a component re-rendering 400 times on a single keystroke.

These are the five optimisations that actually move the needle, in the order you should reach for them. One warning before we start, because it's the most common mistake in this topic: measure before you optimise. Memoizing every component in your app makes it slower, not faster, because memoization itself costs memory and comparison time.


0. Measure First: The React Profiler

Install React DevTools, open the Profiler tab, hit record, and interact with the slow part of your app. You get a flame graph showing exactly which components rendered and how long each took.

Turn on "Highlight updates when components render" in DevTools settings too. If typing in a search box makes your entire page flash, you have a state-placement problem, and no amount of React.memo will fix it properly.

For production monitoring, the <Profiler> component reports real user timings:

import { Profiler } from 'react';

function onRender(id, phase, actualDuration) {
  if (actualDuration > 16) {
    console.warn(`${id} took ${actualDuration.toFixed(1)}ms (${phase})`);
  }
}

<Profiler id="ProductList" onRender={onRender}>
  <ProductList items={items} />
</Profiler>

16ms is the budget for one frame at 60fps. Anything slower drops frames.


1. Let the React Compiler Do the Memoization

This is the biggest change in React performance work. The React Compiler (shipped alongside React 19) analyses your components at build time and inserts memoization automatically. In most codebases it removes the need to write useMemo, useCallback, and React.memo by hand.

Install it as a Babel plugin:

npm install --save-dev babel-plugin-react-compiler
// babel.config.js
module.exports = {
  plugins: [
    ['babel-plugin-react-compiler', { target: '19' }],
  ],
};

The compiler only optimises components that follow the Rules of React. Run the ESLint plugin first to find the ones that don't:

npm install --save-dev eslint-plugin-react-hooks@latest

If you're on React 19 and starting fresh, enable the compiler and skip most of section 2. If you're on React 18 or have a large legacy codebase, manual memoization is still your tool — read on.


2. Manual Memoization: memo, useMemo, useCallback

React.memo skips re-rendering a component when its props haven't changed by shallow comparison:

import { memo } from 'react';

const ProductRow = memo(function ProductRow({ product, onSelect }) {
  console.log('rendering', product.id);
  return (
    <li onClick={() => onSelect(product.id)}>
      {product.name} — ${product.price}
    </li>
  );
});

export default ProductRow;

Here is the catch that makes most memo usage useless. If the parent passes a new object or function on every render, the shallow comparison fails every time and memo does nothing but add overhead:

// BROKEN — a new function identity on every parent render,
// so memo() never prevents anything
<ProductRow product={p} onSelect={(id) => setSelected(id)} />

Stabilise the function with useCallback, and any derived object with useMemo:

import { useCallback, useMemo, useState } from 'react';

function ProductList({ products, query }) {
  const [selected, setSelected] = useState(null);

  // Stable identity across renders — memo() can now do its job
  const handleSelect = useCallback((id) => {
    setSelected(id);
  }, []);

  // Only re-filters when products or query actually change
  const visible = useMemo(
    () => products.filter((p) => p.name.includes(query)),
    [products, query]
  );

  return (
    <ul>
      {visible.map((p) => (
        <ProductRow key={p.id} product={p} onSelect={handleSelect} />
      ))}
    </ul>
  );
}

Use useMemo for genuinely expensive work — filtering thousands of rows, parsing, heavy maths. Wrapping a + b in useMemo costs more than it saves.


3. Code Splitting with lazy and Suspense

Every route and heavy dependency shipped in your initial bundle delays first paint. lazy() defers loading until the component is actually rendered:

import { lazy, Suspense } from 'react';

// Not downloaded until the user opens the dashboard
const Dashboard = lazy(() => import('./pages/Dashboard'));
const ChartEditor = lazy(() => import('./pages/ChartEditor'));

function App() {
  return (
    <Suspense fallback={<PageSkeleton />}>
      <Routes>
        <Route path="/dashboard" element={<Dashboard />} />
        <Route path="/editor" element={<ChartEditor />} />
      </Routes>
    </Suspense>
  );
}

Split at route boundaries first — that's where the payoff is largest. Then split individually heavy components: rich text editors, charting libraries, date pickers, map widgets. A single charting library can be 300KB on its own.

Use a real skeleton as the fallback rather than a spinner. Swapping a spinner for content causes layout shift, which hurts your Cumulative Layout Shift score.


4. Virtualize Long Lists

Rendering 5,000 rows creates 5,000 DOM nodes, and the browser has to lay out and paint every one. Virtualization renders only what's visible plus a small buffer:

npm install react-window
import { FixedSizeList } from 'react-window';

function Row({ index, style, data }) {
  const product = data[index];
  return (
    <div style={style} className="row">
      {product.name} — ${product.price}
    </div>
  );
}

function ProductTable({ products }) {
  return (
    <FixedSizeList
      height={600}
      width="100%"
      itemCount={products.length}
      itemSize={48}
      itemData={products}
    >
      {Row}
    </FixedSizeList>
  );
}

That style prop is mandatory — it carries the absolute positioning that puts each row in the right place. Forgetting to spread it is the number one reason people's first virtualized list renders as a stack of overlapping rows.

For rows of differing heights use VariableSizeList, or @tanstack/react-virtual if you need grid layouts and dynamic measurement.


5. Fix State Placement and Context Re-renders

This is the optimisation people reach for last and should reach for first, because it addresses the cause rather than the symptom.

Colocate state. State lives too high in most component trees. If only one subtree reads a value, move the state into that subtree:

// BEFORE — typing re-renders Header, Sidebar and Footer
function App() {
  const [query, setQuery] = useState('');
  return (
    <>
      <Header />
      <Sidebar />
      <SearchBox value={query} onChange={setQuery} />
      <Results query={query} />
      <Footer />
    </>
  );
}

// AFTER — typing only re-renders SearchPanel's subtree
function SearchPanel() {
  const [query, setQuery] = useState('');
  return (
    <>
      <SearchBox value={query} onChange={setQuery} />
      <Results query={query} />
    </>
  );
}

Split your contexts. Every consumer of a context re-renders when any part of its value changes. A single "AppContext" holding user, theme, and cart means changing the cart re-renders every component reading the theme. Split them by update frequency:

// One context per concern, not one context for everything
<ThemeContext.Provider value={theme}>        {/* changes rarely */}
  <UserContext.Provider value={user}>        {/* changes on login */}
    <CartContext.Provider value={cart}>      {/* changes constantly */}
      {children}
    </CartContext.Provider>
  </UserContext.Provider>
</ThemeContext.Provider>

And always memoize a context value that's an object literal, or you create a new identity on every provider render:

const value = useMemo(() => ({ user, logout }), [user, logout]);

return <UserContext.Provider value={value}>{children}</UserContext.Provider>;

What About Arrow Functions in JSX?

You'll see advice saying never write onClick={() => doThing()} in JSX. This is overstated. Creating a function is cheap, and for a plain DOM element like <button> it costs essentially nothing.

It matters in exactly one case: when the receiving component is wrapped in React.memo, because the new identity defeats the memo comparison. That's the situation useCallback exists for. Everywhere else, inline arrows are fine and far more readable.


Conclusion

If you take one thing from this: profile first, fix state placement second, and memoize last. Most React performance problems are really state-architecture problems wearing a disguise, and moving state closer to where it's used fixes them more thoroughly than any amount of memo.

If you're on React 19, turn the compiler on and let it handle the memoization you'd otherwise write by hand. Then spend your effort on the things it can't do for you — code splitting, virtualization, and sensible context boundaries.

For a broader look at front-end speed beyond React itself, see Mastering Frontend Performance Optimization.

Comments

Popular posts from this blog

Understanding SQL Query Execution Order

When writing SQL queries, understanding the execution order is crucial for writing efficient and optimized code. Many beginners assume that queries execute in the order they are written, but in reality, SQL follows a specific sequence of execution. SQL Execution Order SQL queries run in the following order: 1️⃣ FROM + JOIN 2️⃣ WHERE 3️⃣ GROUP BY 4️⃣ HAVING 5️⃣ SELECT (including window functions) 6️⃣ ORDER BY 7️⃣ LIMIT Let’s break down each step with examples. 1. FROM + JOIN (Data Retrieval) The SQL engine first retrieves data from the specified table(s) and applies any JOIN operations. 🔹 Example: SELECT employees.name, departments.department_name FROM employees JOIN departments ON employees.department_id = departments.id; Here, the JOIN happens before any filtering ( WHERE ) or grouping ( GROUP BY ). 2. WHERE (Filtering Data) Once data is retrieved, the WHERE clause filters rows before aggregation occurs. 🔹 Example: SELECT * FROM employees WHERE salary > 50000 ; Thi...

Best Practices for Securing Personal and Business Data in 2025

In today’s digital landscape, cybersecurity is more critical than ever. With increasing cyber threats, data breaches, and privacy concerns, individuals and businesses must take proactive steps to secure their data. This guide outlines the most effective security practices for 2025. 1. Implement Strong Authentication Measures Passwords alone are no longer sufficient to protect sensitive accounts. Instead, consider: ✅ Multi-Factor Authentication (MFA): Require users to verify their identity using an additional factor, such as an SMS code, authenticator app, or biometric authentication. ✅ Passkeys & Password Managers: Use passkeys where available and store strong, unique passwords in a secure password manager. 2. Encrypt Sensitive Data Encryption ensures that even if data is stolen, it remains unreadable without the decryption key. 🔹 Use end-to-end encryption (E2EE) for messages and emails. 🔹 Encrypt stored data on cloud services, external drives, and local machines. 🔹 Consider ...