3810 stories
·
3 followers

State and rerenders

1 Share

State-based vs Signal-based rendering

When we think about state management in front-end frameworks, we often focus on the API—hooks, observables, or signals. However, there's a deeper paradigm shift at play: where rendering happens. Traditional state management like React hooks triggers renders at the point where state is created, while signal-based approaches like Preact Signals or Solid.js trigger renders only where state is consumed.

This shift from "render where you create state" to "render where you use state" has profound implications for performance, code organization, and mental models.

The Core Difference

In traditional state management with React hooks, when you call useState, any update to that state causes the component—and all its descendants—to re-render. It doesn't matter whether those descendants actually use the state; they're caught in the render wave simply because they're children of the component that holds the state.

const Parent = () => {
  const [count, setCount] = useState(0);
  return (
    <>
      {/* re-renders even though it doesn't use count */}
      <ChildA />
      <ChildB />
      {/* re-renders, actually uses count */}
      <ChildC count={count} />
    </>
  );
};

With signal-based rendering, the paradigm inverts. A signal is a reactive primitive that tracks its own dependencies. When you create a signal, it doesn't trigger re-renders at the creation site. Instead, rendering only occurs at components that actually access the signal's value.

const Parent = () => {
  const count = useSignal(0);
  return (
    <>
      {/* do NOT re-render */}
      <ChildA />
      <ChildB />
      {/* only re-renders if it reads count.value */}
      <ChildC count={count} />
    </>
  );
};

This granular reactivity means only the precise components that depend on the signal will re-render when it updates. The mental model shifts from "prevent unnecessary re-renders" to "re-renders only happen where they're needed."

Context: The Paradigm Shift Amplified

This difference becomes even more pronounced when dealing with the Context API. In React, when you distribute state through context and update it, all consumers of that context re-render, regardless of whether they actually read the updated value.

const CountContext = createContext();

const Provider = ({ children }) => {
  const [count, setCount] = useState(0);
  const [name, setName] = useState('');
  return (
    <CountContext.Provider
      value={{ count, name, setCount, setName }}
    >
      {children}
    </CountContext.Provider>
  );
};

const ComponentA = () => {
  const { name } = useContext(CountContext);
  // Re-renders when count changes,
  // even though it only uses name.
  return <div>{name}</div>;
};

With signals in context, the reactivity is surgical. The context can hold signals, and only components that actually call .value on a signal will subscribe to its updates.

const CountContext = createContext();

const Provider = ({ children }) => {
  const count = useSignal(0);
  const name = useSignal('');
  return (
    <CountContext.Provider value={{ count, name }}>
      {children}
    </CountContext.Provider>
  );
};

const ComponentA = () => {
  const { name } = useContext(CountContext);
  // Only re-renders when name changes,
  // not when count changes
  return <div>{name.value}</div>;
};

This is a game-changer for large applications where context is used to distribute state across many components. You no longer need to split contexts to prevent unnecessary re-renders or reach for complex optimization patterns.

Rendering Propagation

Let's visualize how re-renders propagate through a component tree:

State-Based (React Hooks)

In state-based rendering, when state updates, the entire subtree from the point of state creation re-renders. You need to manually optimize with React.memo, shouldComponentUpdate, useMemo, and useCallback to prevent unnecessary work.

All descendants re-render (shown in red), regardless of whether they actually use the state. Only GC 2 genuinely needs the update, but Child 1, Child 2, Child 3, GC 1, and GC 3 all re-render unnecessarily.

Signal-Based (Preact Signals / Solid.js)

In signal-based rendering, only components that actually read the signal's value re-render. The component hierarchy is irrelevant—what matters is data dependency, not component ancestry.

Only GC 2, which actually accesses signal.value, re-renders (shown in green). All other components remain unchanged (shown in gray), even though they're part of the same component tree.

Granular Control with Control Flow

Preact has a few utilities to take this further with control flow components like Show and For. These components scope reactivity even more precisely.

const items = signal([]);
// When the items signal updates, only the affected items re-render
<For each={items}>
  {(item) => (
    <div>
      {/* Only this item re-renders when item.value changes */}
      <span>{item.name.value}</span>
      <button
        onClick={() => item.count.value++}
      >
        {item.count.value}
      </button>
    </div>
  )}
</For>

Compare this to classic hooks, where changing an item in a list might trigger re-renders across sibling items, the parent component, and any other children—unless you've carefully memoized everything.

These control-flow components scope the re-render of a Signal (be that a derived computed or plain signal value) down to its JSX children.

Performance Implications

This paradigm shift has tangible performance implications:

  • Less computational work: Fewer components re-render means less JavaScript execution. You're not running render functions, diffing virtual DOM, or applying effects for components that don't care about the state change.
  • Reduced bundle size: No need for memoization helpers like React.memo, shouldComponentUpdate, useMemo, or useCallback. The framework's reactivity system handles optimization automatically.
  • Predictable performance: Re-render locations are determined by where signals are accessed, not by component hierarchy. This makes performance predictable and debugging easier—you can trace which components update by following signal reads.
  • No prop drilling: Signals can be passed through context or even imported directly without triggering unnecessary re-renders. You're not forced to split contexts or create provider pyramids.

When State-Based Makes Sense

It's worth noting that state-based rendering isn't inherently bad. For small components or applications where re-renders are cheap, the hooks model is simple and sufficient. The cost of re-rendering a few dozen components is often negligible.

The trade-off becomes significant in:

  • Large component trees with deep nesting
  • High-frequency updates (animations, real-time data)
  • Applications with complex state distribution (multiple contexts, global state)

Conclusion

The shift from state-based to signal-based rendering is more than a performance optimization—it's a paradigm shift in how we think about reactivity. Instead of preventing re-renders through memoization, we only trigger re-renders where they're needed.

This inversion—from "render where you create state" to "render where you use state"—aligns our code with the actual data flow. It makes applications faster by default and simplifies the mental model: if you read a signal, you'll update when it changes. If you don't, you won't.

As frameworks like Preact Signals and Solid.js demonstrate, this isn't a theoretical improvement—it's a practical one that makes building performant, maintainable applications easier. The future of front-end reactivity is fine-grained, and it's already here.

Read the whole story
emrox
4 hours ago
reply
Hamburg, Germany
Share this story
Delete

Physics Insight

2 Comments and 6 Shares
When Galileo dropped two weights from the Leaning Tower of Pisa, they put him in the history books. But when I do it, I get 'detained by security' for 'injuring several tourists.'
Read the whole story
emrox
6 days ago
reply
Hamburg, Germany
Share this story
Delete
2 public comments
llucax
7 days ago
reply
It happened to me too.
Berlin
alt_text_bot
7 days ago
reply
When Galileo dropped two weights from the Leaning Tower of Pisa, they put him in the history books. But when I do it, I get 'detained by security' for 'injuring several tourists.'

HTML’s Best Kept Secret: The output Tag

1 Share

Comments

Read the whole story
emrox
7 days ago
reply
Hamburg, Germany
Share this story
Delete

Introducing the React Foundation: The New Home for React & React Native

2 Shares

Meta open-sourced React over a decade ago to help developers build better user experiences. Since then, React has grown into one of the world’s most popular open source projects, powering over 50 million websites and products built by companies such as Microsoft, Shopify, Bloomberg, Discord, Coinbase, the NFL, and many others. With React Native, React has expanded to support platforms beyond the web, including mobile, tablets, desktops, TVs, gaming consoles, and even mixed reality devices.

This incredible growth is thanks to the thousands of educators, companies, and projects that have contributed to the development of React. The community is the heart of React, and we’re proud to play a part in the cycle of open source innovation throughout the ecosystem that benefits everyone. We’re pleased to give a seat at the table to the people and companies that have made React what it is today.

Today, we are excited to announce the next step for React. Several projects within the React ecosystem, including React and React Native, as well as supporting projects such as JSX, will transition to the React Foundation. The React Foundation’s mission is to help the React community and its members. The React Foundation will maintain React’s infrastructure, organize React Conf, and create initiatives to support the React ecosystem. The React Foundation will be part of the Linux Foundation, which has long fostered a vendor-neutral environment for open source projects.

Formalizing Governance

The React Foundation’s governing board will consist of representatives from Amazon, Callstack, Expo, Meta, Microsoft, Software Mansion, and Vercel, with the intention to expand further over time.

There will be a clear separation between the business and technical governance of React. Releases, features, and technical direction will be governed by a new structure driven by the maintainers and contributors of React. This new technical governance structure will be independent of the React Foundation. The React team is actively working on this new technical governance structure and will share more details in a future post on the React blog.

Meta and the React Foundation

Meta is committing to a five-year partnership with the React Foundation, including over $3 million in funding and dedicated engineering support. This investment will ensure React’s smooth transition to independent governance while maintaining the stability and innovation the community expects. Meta will continue to invest in React and use it as our primary tool for building UI on the web and across many of Meta’s apps. Meta will also continue to have a dedicated team of engineers working full-time on React and React Native.

We believe the best of React is yet to come. The React Foundation will unlock new opportunities for collaboration, innovation, and growth that will benefit the entire ecosystem. We’re excited to see what the community will build together under this new model. With strengthened governance, broader industry participation, and continued technical excellence, React is positioned to tackle the next generation of challenges in UI development.

The post Introducing the React Foundation: The New Home for React & React Native appeared first on Engineering at Meta.

Read the whole story
emrox
11 days ago
reply
Hamburg, Germany
alvinashcraft
13 days ago
reply
Pennsylvania, USA
Share this story
Delete

What You Need to Know about Modern CSS (2025 Edition)

1 Share
Read the whole story
emrox
14 days ago
reply
Hamburg, Germany
Share this story
Delete

“Your” vs “My” in user interfaces

1 Share

When referring to the user’s stuff, which is better out of these:

  • “My account” or “Your account”?
  • “My orders” or “Your orders”?
  • “My cases” or “Your cases”?

It’s a trick question because often you don’t need any prefix and can just use:

  • Account
  • Orders
  • Cases

Amazon is a good example of this in action because it’s obvious that it’s your account and your orders:

But what if your product contains things that belong to you and to others – for example, a case working system that contains your cases and everyone else‘s?

The problem with “my”

You could use “My cases” in a navigation menu like this:

This seems fine on the face of it.

But screens are not only accessed or referred to through a menu.

For example, you might need to sign post users to their cases in an onboarding flow, email notification or help article.

Saying something like “Go to my cases” is awkward and unnatural – if I told you to go to my cases, you’d think I was telling you to go to my cases, not yours.

Similarly, a support agent might tell you to “Go to your cases” over webchat or a phone call. This is confusing if the UI says “My cases”.

These issues just don’t come up when you use “your” – I’ve used this approach in multiple products over the years, and seen exactly zero issues in user research.

So that’s good.

“But what if the user is communicating to us using radio buttons, for example?”

This is easy if we look at an example:

This doesn’t make sense because it sounds like you’re instructing the computer to share their profile, not yours.

But it’s clear if you use “my”:

In summary:

  • Use “your” when communicating to the user
  • Use “my” when the user is communicating to us

If you’d like to design forms that nail basic details like this, as well as complex problems found in enterprise systems, you might like my course, Form Design Mastery:

https://formdesignmastery.com

Read the whole story
emrox
34 days ago
reply
Hamburg, Germany
Share this story
Delete
Next Page of Stories