Storybook Controls Not Updating: A Diagnostic Guide for React Stories
Controls panel edits not re-rendering your React story? Diagnose the stale-props problem with an ordered checklist covering addon registration, args wiring, decorators, and webpack aliases.
15 Dec 2025, 06:12 UTC

You drag a slider in the Controls panel and nothing happens. The rendered component keeps showing the old prop value, the args table looks correct, and there is no error in sight. This is one of the most common Storybook annoyances in React projects, and it almost always comes down to wiring: the Controls addon is present but not actually feeding args into your story, or something in your build config is intercepting it.
The good news: you can diagnose this in about ten minutes by checking a small set of causes in order. This guide assumes Storybook 6.x or later with the Component Story Format (CSF) and the @storybook/react framework. If you are on Storybook 5.x or earlier, upgrade first — Controls as an addon did not exist in its current form before 6.0.
The recognizable condition
The symptoms are consistent:
- Editing a value in the Controls panel does not re-render the component.
- The Controls panel itself works — inputs respond, values change in the panel — but the canvas stays stale.
- Sometimes the panel is entirely empty, or shows only a subset of the props you expect.
- Occasionally you see a console warning about a missing decorator or a peer dependency mismatch.
If instead your component re-renders but with wrong values, that is a different problem (usually an arg mapping issue in the story itself), and the checks below will still help you rule out the addon wiring.
Cause and diagnostic table
| Symptom | Likely cause | Quick check |
|---|---|---|
| Controls panel missing entirely | Addon not registered in main.js | Inspect the addons array |
| Panel present, edits do nothing | Story does not spread args into the component | Read the story's render/template function |
| Panel works in some stories, not others | Decorator applied per-story instead of globally, or duplicated | Compare preview.js with story-level decorators |
| Controls broke after a webpack change | Alias conflict shadowing React or Storybook internals | Review webpackFinal in main.js |
| Warnings about peer dependencies | react/react-dom version mismatch | Compare installed versions to Storybook's requirements |
Ordered checks
Work through these in order; each is cheap and rules out a class of causes.
1. Confirm the Storybook version
Run npx storybook --version in your project root, or check @storybook/react in package.json. Controls require 6.0 or later. If you are behind, upgrade with npx storybook@latest upgrade and follow the migration prompts before debugging anything else.
2. Verify the addon is registered
Open .storybook/main.js and confirm the addons array includes Controls. In most current setups it arrives via @storybook/addon-essentials:
// .storybook/main.js
module.exports = {
stories: ['../src/**/*.stories.@(js|jsx|ts|tsx)'],
addons: [
'@storybook/addon-essentials', // includes controls
],
framework: '@storybook/react',
};If you list addons individually, add '@storybook/addon-controls' explicitly. After any change to main.js, fully restart the Storybook process — addon registration is not hot-reloaded.
3. Check that the story actually consumes args
This is the single most frequent cause. Controls mutate the story's args object; if your story function ignores it, nothing will ever update. A working story passes args through:
// Button.stories.jsx
import { Button } from './Button';
export default {
title: 'Components/Button',
component: Button,
};
// Correct: args flow into the component
const Template = (args) => <Button {...args} />;
export const Primary = Template.bind({});
Primary.args = {
label: 'Click me',
disabled: false,
};The broken variant usually looks like export const Primary = () => <Button label="Click me" /> — hardcoded props, no args parameter. The Controls panel will still render (Storybook infers argTypes from the component), but edits have no effect because the story never reads them.
4. Look for decorator conflicts
If you use a framework preset that already injects controls behavior, adding a duplicate global decorator in preview.js can produce prop-type warnings or swallow updates. Open .storybook/preview.js and remove any custom decorator that wraps stories in a way that drops args — for example, a decorator written as (Story) => <Story /> is fine, but one that clones the story element with fixed props is not.
5. Inspect webpack overrides
A webpackFinal in main.js that aliases react or react-dom to a specific path (a common workaround for monorepos) can cause the addon and your components to load two different React copies. The symptom is exactly "panel works, canvas stale." Check for resolve.alias entries; if you need the alias, scope it so Storybook's own packages resolve consistently, and confirm only one React copy exists with npm ls react (run in the project root; requires no special permissions).
6. Reinstall mismatched peer dependencies
Storybook expects the project's react and react-dom versions to match each other. If the console shows peer dependency warnings at startup, align them (npm install react@^18 react-dom@^18, adjusting for your target major), delete node_modules and the lockfile if versions refuse to settle, and reinstall.
Fixes tied to findings
- Version below 6.0: upgrade Storybook; do not attempt to backport Controls.
- Addon missing: add it to
main.jsand restart the dev server. - Args not consumed: rewrite the story to spread
argsinto the component, as in the example above. - Duplicate decorators: keep one source of global decorators; prefer
preview.jsand remove per-story duplicates. - Webpack alias conflict: remove or narrow the alias; verify a single React copy.
- Peer mismatch: reinstall aligned versions.
One caution: never patch files inside node_modules to force controls to work. The change vanishes on the next install and hides the real configuration problem from the next person.
Verifying the fix
Restart Storybook completely (stop the process, not just the browser tab). Open a story, change a prop in the Controls panel, and confirm the canvas updates in real time. Check the browser console and the terminal for the absence of decorator or peer-dependency warnings. If you use the Storybook test runner, run npx test-storybook against the running instance to confirm stories still render with their default args.
When to escalate
If every check passes and controls still do not update, the problem is likely a genuine bug or an unusual interaction with your build setup. At that point:
- Create a minimal reproduction — a fresh project with one component and one story that shows the failure.
- Run Storybook with debug logging enabled (
SB_DEBUG=1in the environment, or--debug-webpackfor build issues) and capture the output. - File an issue on the Storybook GitHub repository with the reproduction link, your version numbers, and the logs.
In practice, roughly nine out of ten cases are resolved at check 3 — the story simply never consumed its args. Start there if you are in a hurry.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.