开发中使用到storybook作为组件仓库,然后dva是我们的基础架构。
想使用storybook测试、开发组件。
这时候发现无法集成dva进来。研究后方案如下。
首先是storybook的一个节点:common.stories.js
import React from 'react';
import { storiesOf } from '@storybook/react';
import { Provider } from 'react-redux';
import { Header, Footer, Mask, Loading, Toast } from '@/components';
import DrawerDemo from '@/components/Drawer/test';
import store from './configureStore';
// store 的操作
store.dispatch({
type: 'system/showToast',
payload: {
content: '我是个测试toast',
duration: 60 * 60 * 1000,
},
});
const styles = {
mobileContainer: { width: 414, height: 736, border: '1px solid #EAEAEA' },
};
storiesOf('common components', module)
.addDecorator(story => <Provider store={store}>{story()}</Provider>)
.add('Toast ', () => <Toast />)
下面是重点1:configureStore.js 从dva中剥离store
import React from 'react';
import dva from 'dva';
import createLoading from 'dva-loading';
import models from '@/models/index';
import Router from '@/routes/routes';
import '@/assets/styles/normalize.css';
// import store from './configureStore';
// eslint-disable-next-line import/no-extraneous-dependencies
const createHistory = require('history').createBrowserHistory;
const app = dva({ history: createHistory() });
app.use(createLoading());
models.forEach(model => {
app.model(model);
});
app.router(() => <Router />);
app.start();
// eslint-disable-next-line no-underscore-dangle
const store = app._store;
// eslint-disable-next-line no-console
console.log('store', store);
export default store;
最后是使用方式,Toast.js
这里也是个重点,这里有个问题,就是
dva的connect 和redux的connect不是同一个,这个就很尴尬, 尽管我看源码是一样的,但是用下来就是不一样。
最终的解决方案是使用了环境变量动态的去获取用谁的connect,代码如下,分散在三个文件中。
这个是connect.js 用来动态获取connect,最重要的一个hack
/*
* @Chinese description: 兼容 dva 和storybool的 connect
* @English description: use different connect in storybook and project
* @Autor: rjguan
* @Date: 2020-03-11 10:31:32
* @LastEditors: rjguan
* @LastEditTime: 2020-09-16 19:45:53
*/
/* eslint-disable import/no-mutable-exports */
// eslint-disable-next-line import/no-mutable-exports
// eslint-disable-next-line prefer-destructuring
let connect = require('dva').connect;
if (!process.env.REACT_APP_PROJECT) {
// eslint-disable-next-line no-console
console.log('the environment is storybook');
// eslint-disable-next-line global-require
connect = require('react-redux').connect;
} else {
console.log('the environment is project');
}
export default connect;
这个是package.json中设置在script中设置环境变量
"scripts": {
"lint": "eslint src --ext .jsx --ext .js --max-warnings 0 --cache --fix",
"format": "prettier-eslint 'src/**/*.{js,jsx}' --write",
"start": "cross-env REACT_APP_PROJECT=true node scripts/start.js",
"build": "cross-env REACT_APP_PROJECT=true node scripts/build.js",
"test": "cross-env REACT_APP_PROJECT=true node scripts/test.js",
"storybook": "start-storybook -p 9010 -s public"
},
最后在组件中这么用例如 Alert.js
import React, { PureComponent } from 'react';
import connect from '@/utility/connect';
@connect(({ system }) => ({
alert: system.alert,
}))
class Alert extends PureComponent {
...组件内容略
}