5

我正在使用故事书,我想将 redux 添加为装饰器。运行故事书时,我在控制台中收到警告:

<Provider> does not support changing `store` on the fly. It is most likely that you see this error because you updated to Redux 2.x and React Redux 2.x which no longer hot reload reducers automatically. See https://github.com/reactjs/react-redux/releases/tag/v2.0.0 for the migration instructions.

这是我的配置故事书代码:

/* eslint-disable import/no-extraneous-dependencies, import/no-unresolved, import/extensions */

import React from 'react';
import { configure, storiesOf } from '@storybook/react';
import { Provider as ReduxProvider } from 'react-redux';
import forEach from 'lodash/forEach';
import unset from 'lodash/unset';
import Provider from 'components/Provider';
import initStore from 'utils/initStore';
import messages from '../lang/en.json';

const req = require.context('../components', true, /_stories\.js$/);

const ProviderDecorator = (storyFn) => {
  const TheProvider = Provider(() => storyFn());

  return (
    <ReduxProvider store={initStore()}>
      <TheProvider key={Math.random()} now={1499149917064} locale="en" messages={messages} />
    </ReduxProvider>
  );
}

function loadStories() {
  req.keys().forEach((filename) => {
    const data = req(filename);

    if (data.Component !== undefined && data.name !== undefined && data.stories !== undefined) {
      const Component = data.Component;

      const stories = storiesOf(data.name, module);

      stories.addDecorator(ProviderDecorator);

      let decorator = data.stories.__decorator;

      if (data.stories.__decorator !== undefined) {
        stories.addDecorator((storyFn) => data.stories.__decorator(storyFn()));
      }

      forEach(data.stories, (el, key) => {
        if (key.indexOf('__') !== 0) {
          stories.add(key, () => (
            <Component {...el} />
          ));
        }
      });
    } else {
      console.error(`Missing test data for ${filename}!`)
    }

  });
}

configure(loadStories, module);

和 initStore 文件:

import { createStore, applyMiddleware } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import thunkMiddleware from 'redux-thunk';
import { persistStore, autoRehydrate } from 'redux-persist';

import reducers from 'containers/redux/reducers';

export default () => {
  const store = createStore(
    reducers,
    {},
    composeWithDevTools(applyMiddleware(thunkMiddleware), autoRehydrate()),
  );

  if (module.hot) {
    // Enable Webpack hot module replacement for reducers
    module.hot.accept('../containers/redux/reducers', () => {
      const nextReducers = require('../containers/redux/reducers'); // eslint-disable-line global-require
      store.replaceReducer(nextReducers);
    });
  }

  persistStore(store);

  return store;
};

如您所见,我按照警告链接中的说明进行操作。我做错了什么,如何删除此警告?我知道它不会在生产服务器上显示,但在开发模式下很烦人。:/

4

1 回答 1

3

发生这种情况的原因与 Storybook 热加载的方式有关。

当你改变你的故事时,那个模块是热加载的,这意味着它里面的代码会再次被执行。

由于您使用的是存储创建函数而不是来自另一个模块的存储实例,因此ReduxProvider在热加载时传递给的实际存储对象每次都是新的。

但是,重新构建的 React 树在很大程度上是相同的,这意味着ReduxProvider实例是用新的 props 重新渲染而不是重新创建的。

从本质上讲,这正在改变它的商店。

解决方法是确保ReduxProvider实例在热加载时也是新的。这很容易通过传递一个独特的key道具来解决,例如:

const ProviderDecorator = (storyFn) => {
  const TheProvider = Provider(() => storyFn());

  return (
    <ReduxProvider key={Math.random()} store={initStore()}>
      <TheProvider key={Math.random()} now={1499149917064} locale="en" messages={messages} />
    </ReduxProvider>
  );
}

反应键

键帮助 React 识别哪些项目已更改、添加或删除。应为数组内的元素提供键,以使元素具有稳定的身份。

于 2017-11-17T08:43:12.630 回答