diff --git a/addons/background/src/BackgroundPanel.js b/addons/background/src/BackgroundPanel.js
index bf1172ba9230..f03671fcbb63 100644
--- a/addons/background/src/BackgroundPanel.js
+++ b/addons/background/src/BackgroundPanel.js
@@ -63,7 +63,7 @@ export default class BackgroundPanel extends Component {
constructor(props) {
super(props);
- const { channel, api } = props;
+ const { channel } = props;
// A channel is explicitly passed in for testing
if (channel) {
@@ -73,6 +73,20 @@ export default class BackgroundPanel extends Component {
}
this.state = { backgrounds: [] };
+ }
+
+ componentDidMount() {
+ this.iframe = document.getElementById(storybookIframe);
+
+ if (!this.iframe) {
+ throw new Error('Cannot find Storybook iframe');
+ }
+
+ Object.keys(style.iframe).forEach(prop => {
+ this.iframe.style[prop] = style.iframe[prop];
+ });
+
+ const { api } = this.props;
this.channel.on('background-set', backgrounds => {
this.setState({ backgrounds });
@@ -93,18 +107,6 @@ export default class BackgroundPanel extends Component {
});
}
- componentDidMount() {
- this.iframe = document.getElementById(storybookIframe);
-
- if (!this.iframe) {
- throw new Error('Cannot find Storybook iframe');
- }
-
- Object.keys(style.iframe).forEach(prop => {
- this.iframe.style[prop] = style.iframe[prop];
- });
- }
-
setBackgroundFromSwatch = background => {
this.updateIframe(background);
this.props.api.setQueryParams({ background });
diff --git a/addons/background/src/index.js b/addons/background/src/index.js
index d74e08d6da5c..d4b65008310e 100644
--- a/addons/background/src/index.js
+++ b/addons/background/src/index.js
@@ -7,7 +7,7 @@ export class BackgroundDecorator extends React.Component {
constructor(props) {
super(props);
- const { channel, story } = props;
+ const { channel } = props;
// A channel is explicitly passed in for testing
if (channel) {
@@ -15,26 +15,18 @@ export class BackgroundDecorator extends React.Component {
} else {
this.channel = addons.getChannel();
}
-
- this.story = story();
}
- componentWillMount() {
+ componentDidMount() {
this.channel.emit('background-set', this.props.backgrounds);
}
- componentWillReceiveProps(nextProps) {
- if (nextProps.story !== this.props.story) {
- this.story = nextProps.story();
- }
- }
-
componentWillUnmount() {
this.channel.emit('background-unset');
}
render() {
- return this.story;
+ return this.props.story();
}
}
BackgroundDecorator.propTypes = {
diff --git a/addons/centered/package.json b/addons/centered/package.json
index 560382700aac..305c427bc71a 100644
--- a/addons/centered/package.json
+++ b/addons/centered/package.json
@@ -14,7 +14,7 @@
"global": "^4.3.2"
},
"devDependencies": {
- "react-dom": "^16.2.0"
+ "react-dom": "^16.3.0"
},
"peerDependencies": {
"react": "*"
diff --git a/addons/info/package.json b/addons/info/package.json
index f75261451dbb..11b67b8d06f8 100644
--- a/addons/info/package.json
+++ b/addons/info/package.json
@@ -30,7 +30,7 @@
"devDependencies": {
"@storybook/addon-actions": "4.0.0-alpha.1",
"@storybook/react": "4.0.0-alpha.1",
- "react-test-renderer": "^16.1.0"
+ "react-test-renderer": "^16.3.0"
},
"peerDependencies": {
"react": "*",
diff --git a/addons/knobs/src/components/Panel.js b/addons/knobs/src/components/Panel.js
index dcfd959d1210..3763cef2d964 100644
--- a/addons/knobs/src/components/Panel.js
+++ b/addons/knobs/src/components/Panel.js
@@ -60,6 +60,9 @@ export default class Panel extends React.Component {
this.lastEdit = getTimestamp();
this.loadedFromUrl = false;
+ }
+
+ componentDidMount() {
this.props.channel.on('addon:knobs:setKnobs', this.setKnobs);
this.props.channel.on('addon:knobs:setOptions', this.setOptions);
diff --git a/addons/links/package.json b/addons/links/package.json
index 6a837f4811ba..e0259c32c784 100644
--- a/addons/links/package.json
+++ b/addons/links/package.json
@@ -30,8 +30,8 @@
"devDependencies": {
"@storybook/react": "4.0.0-alpha.1",
"enzyme": "^3.3.0",
- "react": "^16.1.0",
- "react-dom": "^16.1.0"
+ "react": "^16.3.0",
+ "react-dom": "^16.3.0"
},
"peerDependencies": {
"@storybook/addons": "^3.3.0",
diff --git a/addons/storyshots/package.json b/addons/storyshots/package.json
index 3fa5df8054c1..4a6a9c04006f 100644
--- a/addons/storyshots/package.json
+++ b/addons/storyshots/package.json
@@ -32,8 +32,8 @@
"@storybook/addons": "4.0.0-alpha.1",
"@storybook/react": "4.0.0-alpha.1",
"enzyme-to-json": "^3.3.3",
- "react": "^16.1.0",
- "react-dom": "^16.1.0"
+ "react": "^16.3.0",
+ "react-dom": "^16.3.0"
},
"peerDependencies": {
"@storybook/addons": "4.0.0-alpha.1",
diff --git a/addons/storysource/src/StoryPanel.js b/addons/storysource/src/StoryPanel.js
index 815e0390a931..eb4afd34ba2b 100644
--- a/addons/storysource/src/StoryPanel.js
+++ b/addons/storysource/src/StoryPanel.js
@@ -46,7 +46,13 @@ export default class StoryPanel extends Component {
this.state = { source: '// Here will be dragons 🐉' };
- const { channel } = props;
+ this.setSelectedStoryRef = this.setSelectedStoryRef.bind(this);
+ this.lineRenderer = this.lineRenderer.bind(this);
+ this.clickOnStory = this.clickOnStory.bind(this);
+ }
+
+ componentDidMount() {
+ const { channel } = this.props;
channel.on(EVENT_ID, ({ source, currentLocation, locationsMap }) => {
const locationsKeys = StoryPanel.getLocationKeys(locationsMap);
@@ -58,10 +64,6 @@ export default class StoryPanel extends Component {
locationsKeys,
});
});
-
- this.setSelectedStoryRef = this.setSelectedStoryRef.bind(this);
- this.lineRenderer = this.lineRenderer.bind(this);
- this.clickOnStory = this.clickOnStory.bind(this);
}
componentDidUpdate() {
diff --git a/app/mithril/package.json b/app/mithril/package.json
index 74db4c70857c..282a80b655ca 100644
--- a/app/mithril/package.json
+++ b/app/mithril/package.json
@@ -49,8 +49,8 @@
"html-webpack-plugin": "^3.1.0",
"json5": "^0.5.1",
"markdown-loader": "^2.0.2",
- "react": "^16.2.0",
- "react-dom": "^16.2.0",
+ "react": "^16.3.0",
+ "react-dom": "^16.3.0",
"util-deprecate": "^1.0.2",
"webpack": "^4.4.1",
"webpack-hot-middleware": "^2.21.2"
diff --git a/app/polymer/package.json b/app/polymer/package.json
index c83b94251af0..3a0cb2f63a7e 100644
--- a/app/polymer/package.json
+++ b/app/polymer/package.json
@@ -49,8 +49,8 @@
"global": "^4.3.2",
"html-webpack-plugin": "^3.1.0",
"json5": "^0.5.1",
- "react": "^16.0.0",
- "react-dom": "^16.0.0",
+ "react": "^16.3.0",
+ "react-dom": "^16.3.0",
"util-deprecate": "^1.0.2",
"webpack": "^4.4.1",
"webpack-hot-middleware": "^2.21.2"
diff --git a/app/react-native/package.json b/app/react-native/package.json
index a4bbf39306b7..3852253bec5d 100644
--- a/app/react-native/package.json
+++ b/app/react-native/package.json
@@ -48,6 +48,7 @@
"babel-runtime": "^6.26.0",
"case-sensitive-paths-webpack-plugin": "^2.1.2",
"commander": "^2.15.1",
+ "dotenv-webpack": "^1.5.5",
"express": "^4.16.3",
"find-cache-dir": "^1.0.0",
"global": "^4.3.2",
diff --git a/app/react-native/src/server/config/webpack.config.js b/app/react-native/src/server/config/webpack.config.js
index 3c00319851b5..0389b5d0cd9e 100644
--- a/app/react-native/src/server/config/webpack.config.js
+++ b/app/react-native/src/server/config/webpack.config.js
@@ -1,5 +1,6 @@
import path from 'path';
import webpack from 'webpack';
+import Dotenv from 'dotenv-webpack';
import WatchMissingNodeModulesPlugin from '@storybook/react-dev-utils/WatchMissingNodeModulesPlugin';
import CaseSensitivePathsPlugin from 'case-sensitive-paths-webpack-plugin';
import HtmlWebpackPlugin from 'html-webpack-plugin';
@@ -27,6 +28,7 @@ const getConfig = options => ({
new webpack.HotModuleReplacementPlugin(),
new CaseSensitivePathsPlugin(),
new WatchMissingNodeModulesPlugin(nodeModulesPaths),
+ new Dotenv({ silent: true }),
],
module: {
rules: [
diff --git a/app/react-native/src/server/config/webpack.config.prod.js b/app/react-native/src/server/config/webpack.config.prod.js
index 3235cedb9678..3048db283f5f 100644
--- a/app/react-native/src/server/config/webpack.config.prod.js
+++ b/app/react-native/src/server/config/webpack.config.prod.js
@@ -1,5 +1,6 @@
import path from 'path';
import webpack from 'webpack';
+import Dotenv from 'dotenv-webpack';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import { includePaths, excludePaths } from './utils';
@@ -31,6 +32,7 @@ const getConfig = options => {
}),
new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"production"' }),
new webpack.optimize.DedupePlugin(),
+ new Dotenv({ silent: true }),
],
module: {
rules: [
diff --git a/app/react/package.json b/app/react/package.json
index 2679d2c92969..03800a2de7f2 100644
--- a/app/react/package.json
+++ b/app/react/package.json
@@ -67,7 +67,7 @@
"peerDependencies": {
"babel-core": "^6.26.0 || ^7.0.0-0",
"babel-runtime": ">=6.0.0",
- "react": ">=15.0.0 || ^16.0.0",
- "react-dom": ">=15.0.0 || ^16.0.0"
+ "react": ">=15.0.0",
+ "react-dom": ">=15.0.0"
}
}
diff --git a/app/react/src/client/preview/render.js b/app/react/src/client/preview/render.js
index c5d591e7915a..ed1d1d09af79 100644
--- a/app/react/src/client/preview/render.js
+++ b/app/react/src/client/preview/render.js
@@ -19,12 +19,19 @@ if (isBrowser) {
rootEl = document.getElementById('root');
}
+function render(node, el) {
+ ReactDOM.render(
+ process.env.STORYBOOK_EXAMPLE_APP ? {node} : node,
+ el
+ );
+}
+
export function renderError(error) {
const properError = new Error(error.title);
properError.stack = error.description;
const redBox = ;
- ReactDOM.render(redBox, rootEl);
+ render(redBox, rootEl);
}
export function renderException(error) {
@@ -33,7 +40,7 @@ export function renderException(error) {
const realError = new Error(error.message);
realError.stack = error.stack;
const redBox = ;
- ReactDOM.render(redBox, rootEl);
+ render(redBox, rootEl);
// Log the stack to the console. So, user could check the source code.
logger.error(error.stack);
@@ -49,7 +56,7 @@ export function renderMain(data, storyStore, forceRender) {
const revision = storyStore.getRevision();
const story = storyStore.getStoryWithContext(selectedKind, selectedStory);
if (!story) {
- ReactDOM.render(noPreview, rootEl);
+ render(noPreview, rootEl);
return null;
}
@@ -101,7 +108,7 @@ export function renderMain(data, storyStore, forceRender) {
return renderError(error);
}
- ReactDOM.render(element, rootEl);
+ render(element, rootEl);
return null;
}
diff --git a/app/vue/package.json b/app/vue/package.json
index ae08a16479c1..6d061b5f6152 100644
--- a/app/vue/package.json
+++ b/app/vue/package.json
@@ -47,8 +47,8 @@
"html-webpack-plugin": "^3.1.0",
"json5": "^0.5.1",
"markdown-loader": "^2.0.2",
- "react": "^16.2.0",
- "react-dom": "^16.2.0",
+ "react": "^16.3.0",
+ "react-dom": "^16.3.0",
"util-deprecate": "^1.0.2",
"webpack": "^4.4.1",
"webpack-hot-middleware": "^2.21.2"
diff --git a/examples/angular-cli/.env b/examples/angular-cli/.env
new file mode 100644
index 000000000000..d24e628d2810
--- /dev/null
+++ b/examples/angular-cli/.env
@@ -0,0 +1 @@
+STORYBOOK_EXAMPLE_APP=true
diff --git a/examples/cra-kitchen-sink/package.json b/examples/cra-kitchen-sink/package.json
index 80a0962e18bd..26c1a11e5e19 100644
--- a/examples/cra-kitchen-sink/package.json
+++ b/examples/cra-kitchen-sink/package.json
@@ -13,8 +13,8 @@
"dependencies": {
"global": "^4.3.2",
"prop-types": "^15.6.1",
- "react": "^16.2.0",
- "react-dom": "^16.2.0"
+ "react": "^16.3.0",
+ "react-dom": "^16.3.0"
},
"devDependencies": {
"@storybook/addon-a11y": "4.0.0-alpha.1",
diff --git a/examples/crna-kitchen-sink/.env b/examples/crna-kitchen-sink/.env
new file mode 100644
index 000000000000..d24e628d2810
--- /dev/null
+++ b/examples/crna-kitchen-sink/.env
@@ -0,0 +1 @@
+STORYBOOK_EXAMPLE_APP=true
diff --git a/examples/mithril-kitchen-sink/.env b/examples/mithril-kitchen-sink/.env
new file mode 100644
index 000000000000..d24e628d2810
--- /dev/null
+++ b/examples/mithril-kitchen-sink/.env
@@ -0,0 +1 @@
+STORYBOOK_EXAMPLE_APP=true
diff --git a/examples/mithril-kitchen-sink/.gitignore b/examples/mithril-kitchen-sink/.gitignore
index 6c96c5cff124..56b6cc8a3115 100644
--- a/examples/mithril-kitchen-sink/.gitignore
+++ b/examples/mithril-kitchen-sink/.gitignore
@@ -11,5 +11,4 @@ build
# misc
.DS_Store
-.env
npm-debug.log
diff --git a/examples/official-storybook/.env b/examples/official-storybook/.env
index 03fe9204f809..f088c261657f 100644
--- a/examples/official-storybook/.env
+++ b/examples/official-storybook/.env
@@ -1 +1,2 @@
DISPLAY_WARNING=none
+STORYBOOK_EXAMPLE_APP=true
diff --git a/examples/official-storybook/package.json b/examples/official-storybook/package.json
index 071ba7c7b871..48afe6b6faf5 100644
--- a/examples/official-storybook/package.json
+++ b/examples/official-storybook/package.json
@@ -35,9 +35,9 @@
"global": "^4.3.2",
"paths.macro": "^2.0.2",
"prop-types": "^15.6.1",
- "react": "^16.2.0",
+ "react": "^16.3.0",
"react-chromatic": "^0.8.1",
- "react-dom": "^16.2.0",
+ "react-dom": "^16.3.0",
"uuid": "^3.2.1"
}
}
diff --git a/examples/polymer-cli/.env b/examples/polymer-cli/.env
new file mode 100644
index 000000000000..d24e628d2810
--- /dev/null
+++ b/examples/polymer-cli/.env
@@ -0,0 +1 @@
+STORYBOOK_EXAMPLE_APP=true
diff --git a/examples/react-native-vanilla/.env b/examples/react-native-vanilla/.env
new file mode 100644
index 000000000000..d24e628d2810
--- /dev/null
+++ b/examples/react-native-vanilla/.env
@@ -0,0 +1 @@
+STORYBOOK_EXAMPLE_APP=true
diff --git a/lib/components/src/navigation/routed_link.js b/lib/components/src/navigation/routed_link.js
index eab73e97f724..e3ba954b8a08 100644
--- a/lib/components/src/navigation/routed_link.js
+++ b/lib/components/src/navigation/routed_link.js
@@ -6,18 +6,18 @@ const LEFT_BUTTON = 0;
const isPlainLeftClick = e =>
e.button === LEFT_BUTTON && !e.altKey && !e.ctrlKey && !e.metaKey && !e.shiftKey;
-const wrapOnClick = fn => e => (isPlainLeftClick(e) ? e.preventDefault() || fn(e) : false);
-
export default class RoutedLink extends React.Component {
- constructor(props, ...rest) {
- super(...[props, ...rest]);
+ constructor(...attrs) {
+ super(...attrs);
- const { onClick } = props;
- this.onClick = onClick ? wrapOnClick(onClick) : undefined;
+ this.onClick = this.onClick.bind(this);
}
- componentWillUpdate({ onClick }) {
- this.onClick = wrapOnClick(onClick);
+ onClick(e) {
+ if (isPlainLeftClick(e)) {
+ e.preventDefault();
+ this.props.onClick(e);
+ }
}
render() {
diff --git a/lib/core/package.json b/lib/core/package.json
index 0e8ec803754d..c0be626dde9a 100644
--- a/lib/core/package.json
+++ b/lib/core/package.json
@@ -37,8 +37,6 @@
"postcss-loader": "^2.1.3",
"prop-types": "^15.6.1",
"qs": "^6.5.1",
- "react": "^16.0.0",
- "react-dom": "^16.0.0",
"redux": "^3.7.2",
"serve-favicon": "^2.4.5",
"shelljs": "^0.8.1",
@@ -48,5 +46,9 @@
"webpack": "^4.4.1",
"webpack-dev-middleware": "^3.1.0",
"webpack-hot-middleware": "^2.21.2"
+ },
+ "peerDependencies": {
+ "react": ">=15.0.0",
+ "react-dom": ">=15.0.0"
}
}
diff --git a/lib/ui/package.json b/lib/ui/package.json
index b5719ab9cdc0..12784390dd74 100644
--- a/lib/ui/package.json
+++ b/lib/ui/package.json
@@ -18,7 +18,7 @@
"@storybook/components": "4.0.0-alpha.1",
"@storybook/mantra-core": "^1.7.2",
"@storybook/podda": "^1.2.3",
- "@storybook/react-komposer": "^2.0.3",
+ "@storybook/react-komposer": "^2.0.4",
"babel-runtime": "^6.26.0",
"deep-equal": "^1.0.1",
"events": "^2.0.0",
@@ -33,6 +33,7 @@
"qs": "^6.5.1",
"react-fuzzy": "^0.5.2",
"react-icons": "^2.2.7",
+ "react-lifecycles-compat": "^1.1.0",
"react-modal": "^3.3.2",
"react-split-pane": "^0.1.77",
"react-treebeard": "^2.1.0"
diff --git a/lib/ui/src/libs/withLifecycleDecorator.js b/lib/ui/src/libs/withLifecycleDecorator.js
index df364c630351..9d16977cd126 100644
--- a/lib/ui/src/libs/withLifecycleDecorator.js
+++ b/lib/ui/src/libs/withLifecycleDecorator.js
@@ -3,12 +3,16 @@ import PropTypes from 'prop-types';
// A small utility to add before/afterEach to stories.
class WithLifecyle extends Component {
- componentWillMount() {
- this.props.beforeEach();
+ constructor(props, ...rest) {
+ super(props, ...rest);
+
+ props.beforeEach();
}
+
componentWillUnmount() {
this.props.afterEach();
}
+
render() {
return this.props.storyFn();
}
diff --git a/lib/ui/src/modules/ui/components/layout/dimensions.js b/lib/ui/src/modules/ui/components/layout/dimensions.js
index 3db18d52c4da..ec9f556975d8 100644
--- a/lib/ui/src/modules/ui/components/layout/dimensions.js
+++ b/lib/ui/src/modules/ui/components/layout/dimensions.js
@@ -1,5 +1,6 @@
import PropTypes from 'prop-types';
import React from 'react';
+import polyfill from 'react-lifecycles-compat';
import { baseFonts } from '@storybook/components';
@@ -30,15 +31,19 @@ class Dimensions extends React.Component {
super(props);
this.state = {
+ ...props,
isVisible: false,
};
this.hideTimeout = null;
}
- componentWillReceiveProps({ width, height }) {
- if (width !== this.state.width || height !== this.state.height) {
- this.onChange(width, height);
+ componentDidUpdate() {
+ if (this.state.isVisible) {
+ clearTimeout(this.hideTimeout);
+ this.hideTimeout = setTimeout(() => {
+ this.setState({ isVisible: false });
+ }, DISPLAY_TIMEOUT);
}
}
@@ -46,17 +51,6 @@ class Dimensions extends React.Component {
clearTimeout(this.hideTimeout);
}
- onChange(width, height) {
- this.setState({ isVisible: true });
-
- this.hideTimeout = setTimeout(() => {
- // Ensure the dimensions aren't still changing
- if (width === this.props.width && height === this.props.height) {
- this.setState({ isVisible: false });
- }
- }, DISPLAY_TIMEOUT);
- }
-
render() {
if (!this.state.isVisible) {
return null;
@@ -74,9 +68,18 @@ class Dimensions extends React.Component {
}
}
+Dimensions.getDerivedStateFromProps = (nextProps, prevState) => {
+ if (nextProps.width !== prevState.width || nextProps.height !== prevState.height) {
+ return { ...nextProps, isVisible: true };
+ }
+ return null;
+};
+
Dimensions.propTypes = {
width: PropTypes.number.isRequired,
height: PropTypes.number.isRequired,
};
+polyfill(Dimensions);
+
export default Dimensions;
diff --git a/lib/ui/src/modules/ui/components/search_box.stories.js b/lib/ui/src/modules/ui/components/search_box.stories.js
index b9b6f5eece7b..a4078a99f3ae 100644
--- a/lib/ui/src/modules/ui/components/search_box.stories.js
+++ b/lib/ui/src/modules/ui/components/search_box.stories.js
@@ -1,4 +1,5 @@
import React from 'react';
+import ReactModal from 'react-modal';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { navigator } from 'global';
@@ -14,6 +15,8 @@ const stories = [
const onSelectStory = action('onSelectStory');
const onClose = action('onClose');
+ReactModal.setAppElement('#root');
+
// For some reason react-modal causes an segfault (infinite loop maybe?)
// when rendered by storyshots/react-test-renderer
if (!navigator.userAgent.match(/Node\.js/) && !navigator.userAgent.match(/jsdom/)) {
diff --git a/lib/ui/src/modules/ui/components/stories_panel/stories_tree/index.js b/lib/ui/src/modules/ui/components/stories_panel/stories_tree/index.js
index 907a1db89439..06ec612ece10 100644
--- a/lib/ui/src/modules/ui/components/stories_panel/stories_tree/index.js
+++ b/lib/ui/src/modules/ui/components/stories_panel/stories_tree/index.js
@@ -1,6 +1,7 @@
import { Treebeard } from 'react-treebeard';
import PropTypes from 'prop-types';
import React from 'react';
+import polyfill from 'react-lifecycles-compat';
import deepEqual from 'deep-equal';
import TreeHeader from './tree_header';
import treeNodeTypes from './tree_node_type';
@@ -47,33 +48,6 @@ class Stories extends React.Component {
};
}
- componentWillReceiveProps(nextProps) {
- const {
- selectedHierarchy: nextSelectedHierarchy = [],
- storyFilter: nextStoryFilter,
- } = nextProps;
-
- const {
- selectedHierarchy: currentSelectedHierarchy = [],
- storyFilter: currentStoryFilter,
- } = this.props;
-
- const shouldClearFilteredNodes = nextStoryFilter !== currentStoryFilter;
- const selectedHierarchyChanged = !deepEqual(nextSelectedHierarchy, currentSelectedHierarchy);
-
- if (selectedHierarchyChanged || shouldClearFilteredNodes) {
- const selectedNodes = getSelectedNodes(nextSelectedHierarchy);
-
- this.setState(prevState => ({
- overriddenFilteredNodes: shouldClearFilteredNodes ? {} : prevState.overriddenFilteredNodes,
- nodes: {
- ...prevState.nodes,
- ...selectedNodes,
- },
- }));
- }
- }
-
onToggle(node, toggled) {
if (node.story) {
this.fireOnKindAndStory(node.kind, node.story);
@@ -173,6 +147,30 @@ class Stories extends React.Component {
}
}
+Stories.getDerivedStateFromProps = (nextProps, prevState) => {
+ const { selectedHierarchy = [], storyFilter } = nextProps;
+
+ const { prevSelectedHierarchy = [], prevStoryFilter } = prevState;
+
+ const shouldClearFilteredNodes = storyFilter !== prevStoryFilter;
+ const selectedHierarchyChanged = !deepEqual(selectedHierarchy, prevSelectedHierarchy);
+
+ if (selectedHierarchyChanged || shouldClearFilteredNodes) {
+ const selectedNodes = getSelectedNodes(selectedHierarchy);
+
+ return {
+ overriddenFilteredNodes: shouldClearFilteredNodes ? {} : prevState.overriddenFilteredNodes,
+ nodes: {
+ ...prevState.nodes,
+ ...selectedNodes,
+ },
+ prevSelectedHierarchy: selectedHierarchy,
+ prevStoryFilter: storyFilter,
+ };
+ }
+ return null;
+};
+
Stories.defaultProps = {
onSelectStory: null,
storiesHierarchy: null,
@@ -194,4 +192,6 @@ Stories.propTypes = {
sidebarAnimations: PropTypes.bool,
};
+polyfill(Stories);
+
export default Stories;
diff --git a/lib/ui/src/modules/ui/components/stories_panel/text_filter.js b/lib/ui/src/modules/ui/components/stories_panel/text_filter.js
index 0e88d0ffdc37..df4f214ce013 100755
--- a/lib/ui/src/modules/ui/components/stories_panel/text_filter.js
+++ b/lib/ui/src/modules/ui/components/stories_panel/text_filter.js
@@ -1,5 +1,6 @@
import PropTypes from 'prop-types';
import React from 'react';
+import polyfill from 'react-lifecycles-compat';
import debounce from 'lodash.debounce';
import { baseFonts } from '@storybook/components';
@@ -45,27 +46,17 @@ const clearButtonStyle = {
const debounceFilterChangeTimeout = 500;
-export default class TextFilter extends React.Component {
+class TextFilter extends React.Component {
constructor(props) {
super(props);
- this.state = {
- query: props.text,
- };
+ this.state = {};
this.onChange = this.onChange.bind(this);
this.fireOnClear = this.fireOnClear.bind(this);
this.changeFilter = debounce(this.changeFilter, debounceFilterChangeTimeout);
}
- componentWillReceiveProps(nextProps) {
- if (nextProps.text !== this.state.query) {
- this.setState({
- query: nextProps.text,
- });
- }
- }
-
onChange(event) {
const text = event.target.value;
this.setState({ query: text });
@@ -107,6 +98,16 @@ export default class TextFilter extends React.Component {
}
}
+TextFilter.getDerivedStateFromProps = ({ text }, { prevText }) => {
+ if (text !== prevText) {
+ return {
+ query: text,
+ prevText: text,
+ };
+ }
+ return null;
+};
+
TextFilter.defaultProps = {
text: defaultTextValue,
onChange: null,
@@ -114,7 +115,12 @@ TextFilter.defaultProps = {
};
TextFilter.propTypes = {
+ // eslint-disable-next-line react/no-unused-prop-types
text: PropTypes.string,
onChange: PropTypes.func,
onClear: PropTypes.func,
};
+
+polyfill(TextFilter);
+
+export default TextFilter;
diff --git a/lib/ui/src/modules/ui/routes.js b/lib/ui/src/modules/ui/routes.js
index 79929c704083..5fa050563fce 100755
--- a/lib/ui/src/modules/ui/routes.js
+++ b/lib/ui/src/modules/ui/routes.js
@@ -18,8 +18,10 @@ export default function(injectDeps, { clientStore, provider, domNode }) {
// Tell react-modal which element to mark as aria-hidden
ReactModal.setAppElement(domNode);
+ const Container = process.env.STORYBOOK_EXAMPLE_APP ? React.StrictMode : 'div';
+
const root = (
-
+
}
preview={() => }
@@ -27,7 +29,7 @@ export default function(injectDeps, { clientStore, provider, domNode }) {
/>
-
+
);
ReactDOM.render(root, domNode);
}
diff --git a/package.json b/package.json
index 82edbed5914c..aa5a0d8f596e 100644
--- a/package.json
+++ b/package.json
@@ -89,9 +89,9 @@
"polymer-webpack-loader": "^2.0.2",
"prettier": "^1.11.1",
"raf": "^3.4.0",
- "react": "^16.2.0",
- "react-dom": "^16.2.0",
- "react-test-renderer": "^16.2.0",
+ "react": "^16.3.0",
+ "react-dom": "^16.3.0",
+ "react-test-renderer": "^16.3.0",
"remark-cli": "^5.0.0",
"remark-lint": "^6.0.1",
"remark-preset-lint-recommended": "^3.0.1",
diff --git a/yarn.lock b/yarn.lock
index 03fc4a105c45..80d45cecc62c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -331,7 +331,7 @@
strip-ansi "4.0.0"
text-table "0.2.0"
-"@storybook/react-komposer@^2.0.1", "@storybook/react-komposer@^2.0.3":
+"@storybook/react-komposer@^2.0.1":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@storybook/react-komposer/-/react-komposer-2.0.3.tgz#f9e12a9586b2ce95c24c137eabb8b71527ddb369"
dependencies:
@@ -341,6 +341,16 @@
lodash.pick "^4.4.0"
shallowequal "^0.2.2"
+"@storybook/react-komposer@^2.0.4":
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/@storybook/react-komposer/-/react-komposer-2.0.4.tgz#c2c0d4a75d9b4a9c0c6b46f14ab050f458ad4bb0"
+ dependencies:
+ "@storybook/react-stubber" "^1.0.0"
+ babel-runtime "^6.11.6"
+ hoist-non-react-statics "^1.2.0"
+ lodash.pick "^4.4.0"
+ shallowequal "^0.2.2"
+
"@storybook/react-simple-di@^1.2.1":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@storybook/react-simple-di/-/react-simple-di-1.3.0.tgz#13116d89a2f42898716a7f8c4095b47415526371"
@@ -13040,9 +13050,9 @@ react-docgen@^2.20.0:
node-dir "^0.1.10"
recast "^0.12.6"
-react-dom@^16.0.0, react-dom@^16.1.0, react-dom@^16.2.0:
- version "16.2.0"
- resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.2.0.tgz#69003178601c0ca19b709b33a83369fe6124c044"
+react-dom@^16.0.0, react-dom@^16.3.0:
+ version "16.3.0"
+ resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.3.0.tgz#b318e52184188ecb5c3e81117420cca40618643e"
dependencies:
fbjs "^0.8.16"
loose-envify "^1.1.0"
@@ -13085,6 +13095,14 @@ react-inspector@^2.2.2:
babel-runtime "^6.26.0"
is-dom "^1.0.9"
+react-is@^16.3.0:
+ version "16.3.0"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.3.0.tgz#f0e8bfd8c09b480dd610b8639d9ed65c13601224"
+
+react-lifecycles-compat@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-1.1.0.tgz#6641d0709bd5505329b5c90322147ef2d343485c"
+
react-modal@^3.3.2:
version "3.3.2"
resolved "https://registry.yarnpkg.com/react-modal/-/react-modal-3.3.2.tgz#b13da9490653a7c76bc0e9600323eb1079c620e7"
@@ -13250,7 +13268,7 @@ react-syntax-highlighter@^7.0.2:
prismjs "^1.8.4"
refractor "^2.0.0"
-react-test-renderer@^16.0.0-0, react-test-renderer@^16.1.0, react-test-renderer@^16.2.0:
+react-test-renderer@^16.0.0-0:
version "16.2.0"
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.2.0.tgz#bddf259a6b8fcd8555f012afc8eacc238872a211"
dependencies:
@@ -13258,6 +13276,15 @@ react-test-renderer@^16.0.0-0, react-test-renderer@^16.1.0, react-test-renderer@
object-assign "^4.1.1"
prop-types "^15.6.0"
+react-test-renderer@^16.3.0:
+ version "16.3.0"
+ resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.3.0.tgz#7e88d8cb4c2b95c161b6c6c998991166f74d473e"
+ dependencies:
+ fbjs "^0.8.16"
+ object-assign "^4.1.1"
+ prop-types "^15.6.0"
+ react-is "^16.3.0"
+
react-textarea-autosize@^5.2.1:
version "5.2.1"
resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-5.2.1.tgz#2b78f9067180f41b08ac59f78f1581abadd61e54"
@@ -13296,9 +13323,9 @@ react-treebeard@^2.1.0:
shallowequal "^0.2.2"
velocity-react "^1.3.1"
-react@^16.0.0, react@^16.1.0, react@^16.2.0:
- version "16.2.0"
- resolved "https://registry.yarnpkg.com/react/-/react-16.2.0.tgz#a31bd2dab89bff65d42134fa187f24d054c273ba"
+react@^16.0.0, react@^16.3.0:
+ version "16.3.0"
+ resolved "https://registry.yarnpkg.com/react/-/react-16.3.0.tgz#fc5a01c68f91e9b38e92cf83f7b795ebdca8ddff"
dependencies:
fbjs "^0.8.16"
loose-envify "^1.1.0"