build-storybook differences?
See original GitHub issueI’m trying to figure out a weird edge case I’m having, using mobx for store management inside stories.
Take this (highly convoluted) story:
import React from 'react';
import { observable } from 'mobx';
import { observer } from 'mobx-react';
// Create a new store
const store = observable({
toggle: true,
});
// Toggle the value inside the store
function toggle() {
store.toggle = !store.toggle;
}
// Test component -- uses the store above, but NOT a direct observer
const Headline = props => (
<h1>{props.store.toggle.toString()}</h1>
);
Headline.propTypes = {
store: React.PropTypes.shape({
toggle: React.PropTypes.bool.isRequired,
}),
};
// Generator func to return x number of <Headline> components, fed the store
function* getComponents(count) {
for (let i = 1; i <= count; i++) {
yield (
<Headline key={i} store={store} />
);
}
}
// Wrap THIS one in an observer, and go down the chain
const Toggle = observer(() => (
<div>
{[...getComponents(5)]}
<button
onClick={toggle}>Toggle</button>
</div>
));
// Export as an instantiated JSX comp.
export default <Toggle />;
When running in dev (npm run dev
), clicking ‘toggle’ works fine…
However, when running in production (npm run build-storybook
and starting a local server), toggle suddenly stops working…
My gut reaction is that it has something to do with transpilation differences. Stores built using MobX’s observer
function work differently depending on whether there’s a prototype
chain (if there is, properties on the object are observable, but not the parent object itself). But that doesn’t seem to be happening because in both cases, there’s no prototype chain, and in other examples where the parent store is not fed in but used directly, it works as expected.
It seems the observer chain is ‘lost’ somehow when the generator passes it to it.
I know it’s a totally weird edge case, but are there any known differences between how code is rendered in dev vs. bundling?
Issue Analytics
- State:
- Created 7 years ago
- Comments:8
d’oh, it suddenly makes sense.
.propTypes
isn’t evaluated in production (it’s a dev-only check, right?) So it wouldn’t ‘observe’ the underlying value, and thus wouldn’t re-calculate.So, in this case, .propTypes was causing a side-effect that unintentionally made the component appear to be observing (I guess inside the original call stack passing the prop?), but breaks as soon as
.propTypes
is dropped in production – which is what it should do, because the final component isn’t an observer.Makes sense now!
Something else that is a bit freaky too (maybe related to mobxjs/mobx-react#56)
Under
npm run storybook
, dropping.propTypes
actually prevents it from observing:So I guess that’s exactly what mobxjs/mobx-react#56 relates to – adding a
.propTypes
definition causes a re-render (but only in dev; not in production), thus making the component update vianpm run storybook
but NOTnpm build-storybook
.interesting!