Merge branch 'master' into feature-3.7.0

This commit is contained in:
afc163 2018-07-11 22:21:01 +08:00
commit 8eb8c686ce
25 changed files with 311 additions and 304 deletions

View File

@ -5,20 +5,24 @@ language: node_js
node_js:
- 8
cache:
directories:
- node_modules
matrix:
fast_finish: true
include:
- env: TEST_TYPE=lint
- env: REACT=16 TEST_TYPE=test:dist
- env: REACT=16 TEST_TYPE=test:lib
- env: REACT=16 TEST_TYPE=test:es
- env: REACT=16 TEST_TYPE=test:dom
- env: REACT=16 TEST_TYPE=test:node
- env: REACT=15 TEST_TYPE=test:dist
- env: REACT=15 TEST_TYPE=test:lib
- env: REACT=15 TEST_TYPE=test:es
- env: REACT=15 TEST_TYPE=test:dom
- env: REACT=15 TEST_TYPE=test:node
- env: TEST_TYPE=lint
- env: REACT=16 TEST_TYPE=test:dist
- env: REACT=16 TEST_TYPE=test:lib
- env: REACT=16 TEST_TYPE=test:es
- env: REACT=16 TEST_TYPE=test:dom
- env: REACT=16 TEST_TYPE=test:node
- env: REACT=15 TEST_TYPE=test:dist
- env: REACT=15 TEST_TYPE=test:lib
- env: REACT=15 TEST_TYPE=test:es
- env: REACT=15 TEST_TYPE=test:dom
- env: REACT=15 TEST_TYPE=test:node
before_script:
- scripts/install-react.sh

View File

@ -5,6 +5,7 @@
@alert-message-color: @heading-color;
@alert-text-color: @text-color;
@alert-close-color: @text-color-secondary;
.@{alert-prefix-cls} {
.reset-component;
@ -70,7 +71,7 @@
cursor: pointer;
.@{iconfont-css-prefix}-cross {
color: @text-color-secondary;
color: @alert-close-color;
transition: color .3s;
&:hover {
color: #404040;
@ -87,7 +88,7 @@
padding: 15px 15px 15px 64px;
position: relative;
border-radius: @border-radius-base;
color: @text-color;
color: @alert-text-color;
line-height: @line-height-base;
}

View File

@ -5,6 +5,7 @@ import RangeCalendar from 'rc-calendar/lib/RangeCalendar';
import RcDatePicker from 'rc-calendar/lib/Picker';
import classNames from 'classnames';
import Icon from '../icon';
import Tag from '../tag';
import warning from '../_util/warning';
import interopDefault from '../_util/interopDefault';
import { RangePickerValue, RangePickerPresetRange } from './interface';
@ -211,14 +212,15 @@ export default class RangePicker extends React.Component<any, RangePickerState>
const operations = Object.keys(ranges || {}).map((range) => {
const value = ranges[range];
return (
<a
<Tag
key={range}
color="blue"
onClick={() => this.handleRangeClick(value)}
onMouseEnter={() => this.setState({ hoverValue: value })}
onMouseLeave={this.handleRangeMouseLeave}
>
{range}
</a>
</Tag>
);
});
const rangeNode = (

View File

@ -50,7 +50,7 @@ describe('RangePicker', () => {
);
const rangeCalendarWrapper = mount(wrapper.find('Trigger').instance().getComponent());
rangeCalendarWrapper.find('.ant-calendar-range-quick-selector a')
rangeCalendarWrapper.find('.ant-calendar-range-quick-selector Tag')
.simulate('click');
expect(render(wrapper.find('Trigger').instance().getComponent()))
.toMatchSnapshot();
@ -69,7 +69,7 @@ describe('RangePicker', () => {
);
let rangeCalendarWrapper = mount(wrapper.find('Trigger').instance().getComponent());
rangeCalendarWrapper.find('.ant-calendar-range-quick-selector a')
rangeCalendarWrapper.find('.ant-calendar-range-quick-selector Tag')
.simulate('mouseEnter');
rangeCalendarWrapper = mount(wrapper.find('Trigger').instance().getComponent());
expect(rangeCalendarWrapper.find('.ant-calendar-selected-day').length).toBe(2);
@ -152,7 +152,7 @@ describe('RangePicker', () => {
/>
);
wrapper.find('.ant-calendar-picker-input').simulate('click');
wrapper.find('.ant-calendar-range-quick-selector a').simulate('click');
wrapper.find('.ant-calendar-range-quick-selector Tag').simulate('click');
expect(
wrapper.find('.ant-calendar-range-picker-input').first().getDOMNode().value
).toBe(range[0].format(format));
@ -171,7 +171,7 @@ describe('RangePicker', () => {
/>
);
wrapper.find('.ant-calendar-picker-input').simulate('click');
wrapper.find('.ant-calendar-range-quick-selector a').simulate('click');
wrapper.find('.ant-calendar-range-quick-selector Tag').simulate('click');
expect(
wrapper.find('.ant-calendar-range-picker-input').first().getDOMNode().value
).toBe(range[0].format(format));
@ -200,7 +200,7 @@ describe('RangePicker', () => {
/>
);
wrapper.find('.ant-calendar-picker-input').simulate('click');
wrapper.find('.ant-calendar-range-quick-selector a').simulate('click');
wrapper.find('.ant-calendar-range-quick-selector Tag').simulate('click');
expect(handleOk).toBeCalledWith(range);
});

View File

@ -2990,9 +2990,12 @@ exports[`RangePicker switch to corresponding month panel when click presetted ra
<div
class="ant-calendar-footer-extra ant-calendar-range-quick-selector"
>
<a>
<div
class="ant-tag ant-tag-blue"
data-show="true"
>
My Birthday
</a>
</div>
</div>
<div
class="ant-calendar-footer-btn"

View File

@ -36,8 +36,7 @@ import locale from 'antd/lib/date-picker/locale/zh_CN';
```jsx
// The default locale is en-US, if you want to use other locale, just set locale in entry file globaly.
import moment from 'moment';
import 'moment/src/locale/zh-cn';
// import 'moment/locale/zh-cn'; if you are using webpack 1
import 'moment/locale/zh-cn';
<DatePicker defaultValue={moment('2015-01-01', 'YYYY-MM-DD')} />
```

View File

@ -37,8 +37,7 @@ import locale from 'antd/lib/date-picker/locale/zh_CN';
```jsx
// 默认语言为 en-US如果你需要设置其他语言推荐在入口文件全局设置 locale
import moment from 'moment';
import 'moment/src/locale/zh-cn';
// import 'moment/locale/zh-cn'; if you are using webpack 1
mport 'moment/locale/zh-cn';
<DatePicker defaultValue={moment('2015-01-01', 'YYYY-MM-DD')} />
```

View File

@ -4,3 +4,4 @@ import './index.less';
// style dependencies
import '../../input/style';
import '../../time-picker/style';
import '../../tag/style';

View File

@ -66,6 +66,10 @@ const generateId = (() => {
};
})();
const isNumeric = (n: any) => {
return !isNaN(parseFloat(n)) && isFinite(n);
};
export default class Sider extends React.Component<SiderProps, SiderState> {
static __ANT_LAYOUT_SIDER: any = true;
@ -191,7 +195,7 @@ export default class Sider extends React.Component<SiderProps, SiderState> {
'defaultCollapsed', 'onCollapse', 'breakpoint', 'onBreakpoint']);
const rawWidth = this.state.collapsed ? collapsedWidth : width;
// use "px" as fallback unit for width
const siderWidth = typeof rawWidth === 'number' ? `${rawWidth}px` : String(rawWidth || 0);
const siderWidth = isNumeric(rawWidth) ? `${rawWidth}px` : String(rawWidth);
// special trigger when collapsedWidth == 0
const zeroWidthTrigger = parseFloat(String(collapsedWidth || 0)) === 0 ? (
<span onClick={this.toggle} className={`${prefixCls}-zero-width-trigger`}>

View File

@ -0,0 +1,14 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Layout renders string width correctly 1`] = `
<div
class="ant-layout-sider ant-layout-sider-dark"
style="flex:0 0 200px;max-width:200px;min-width:200px;width:200px"
>
<div
class="ant-layout-sider-children"
>
Sider
</div>
</div>
`;

View File

@ -1,5 +1,5 @@
import React from 'react';
import { mount } from 'enzyme';
import { mount, render } from 'enzyme';
import Layout from '..';
const { Sider, Content } = Layout;
@ -69,6 +69,13 @@ describe('Layout', () => {
);
expect(wrapper.find('.ant-layout-sider').hasClass('ant-layout-sider-light'));
});
it('renders string width correctly', () => {
const wrapper = render(
<Sider width="200">Sider</Sider>
);
expect(wrapper).toMatchSnapshot();
});
});
describe('Sider onBreakpoint', () => {

View File

@ -3,7 +3,11 @@
&-light {
background: @layout-sider-background-light;
}
&-light > &-trigger {
&-light &-trigger {
color: @layout-trigger-color-light;
background: @layout-trigger-background-light;
}
&-light &-zero-width-trigger {
color: @layout-trigger-color-light;
background: @layout-trigger-background-light;
}

View File

@ -14,8 +14,7 @@ title: LocaleProvider
```jsx
import { LocaleProvider } from 'antd';
import fr_FR from 'antd/lib/locale-provider/fr_FR';
import 'moment/src/locale/fr';
// import 'moment/locale/fr'; if you are using webpack 1
import 'moment/locale/fr';
...

View File

@ -15,9 +15,7 @@ LocaleProvider 使用 React 的 [context](https://facebook.github.io/react/docs/
```jsx
import { LocaleProvider } from 'antd';
import zh_CN from 'antd/lib/locale-provider/zh_CN';
import 'moment/src/locale/zh-cn';
// import 'moment/locale/zh-cn'; if you are using webpack 1
import 'moment/locale/zh-cn';
...
return <LocaleProvider locale={zh_CN}><App /></LocaleProvider>;

View File

@ -14,6 +14,8 @@ export default {
filterConfirm: '확인',
filterReset: '초기화',
emptyText: '데이터 없음',
selectAll: '모두 선택',
selectInvert: '선택 반전',
},
Modal: {
okText: '확인',

View File

@ -2746,26 +2746,20 @@ exports[`renders ./components/table/demo/edit-cell.md correctly 1`] = `
class="ant-table-tbody"
>
<tr
class="ant-table-row ant-table-row-level-0"
class="ant-table-row editable-row ant-table-row-level-0"
>
<td
class=""
>
<span
class="ant-table-row-indent indent-level-0"
style="padding-left:0px"
/>
<div
class="editable-cell"
class="editable-cell-value-wrap"
style="padding-right:24px"
>
<div
style="padding-right:24px"
>
Edward King 0
<i
class="anticon anticon-edit editable-cell-icon"
/>
</div>
<span
class="ant-table-row-indent indent-level-0"
style="padding-left:0px"
/>
Edward King 0
</div>
</td>
<td
@ -2789,26 +2783,20 @@ exports[`renders ./components/table/demo/edit-cell.md correctly 1`] = `
</td>
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
class="ant-table-row editable-row ant-table-row-level-0"
>
<td
class=""
>
<span
class="ant-table-row-indent indent-level-0"
style="padding-left:0px"
/>
<div
class="editable-cell"
class="editable-cell-value-wrap"
style="padding-right:24px"
>
<div
style="padding-right:24px"
>
Edward King 1
<i
class="anticon anticon-edit editable-cell-icon"
/>
</div>
<span
class="ant-table-row-indent indent-level-0"
style="padding-left:0px"
/>
Edward King 1
</div>
</td>
<td

View File

@ -14,60 +14,110 @@ title:
Table with editable cells.
````jsx
import { Table, Input, Icon, Button, Popconfirm } from 'antd';
import { Table, Input, Button, Popconfirm, Form } from 'antd';
const FormItem = Form.Item;
const EditableContext = React.createContext();
const EditableRow = ({ form, index, ...props }) => (
<EditableContext.Provider value={form}>
<tr {...props} />
</EditableContext.Provider>
);
const EditableFormRow = Form.create()(EditableRow);
class EditableCell extends React.Component {
state = {
value: this.props.value,
editable: false,
editing: false,
}
handleChange = (e) => {
const value = e.target.value;
this.setState({ value });
}
check = () => {
this.setState({ editable: false });
if (this.props.onChange) {
this.props.onChange(this.state.value);
componentDidMount() {
if (this.props.editable) {
document.addEventListener('click', this.handleClickOutside, true);
}
}
edit = () => {
this.setState({ editable: true });
componentWillUnmount() {
if (this.props.editable) {
document.removeEventListener('click', this.handleClickOutside, true);
}
}
toggleEdit = () => {
const editing = !this.state.editing;
this.setState({ editing }, () => {
if (editing) {
this.input.focus();
}
});
}
handleClickOutside = (e) => {
const { editing } = this.state;
if (editing && this.cell !== e.target && !this.cell.contains(e.target)) {
this.save();
}
}
save = () => {
const { record, handleSave } = this.props;
this.form.validateFields((error, values) => {
if (error) {
return;
}
this.toggleEdit();
handleSave({ ...record, ...values });
});
}
render() {
const { value, editable } = this.state;
const { editing } = this.state;
const {
editable,
dataIndex,
title,
record,
index,
handleSave,
...restProps
} = this.props;
return (
<div className="editable-cell">
{
editable ? (
<Input
value={value}
onChange={this.handleChange}
onPressEnter={this.check}
suffix={(
<Icon
type="check"
className="editable-cell-icon-check"
onClick={this.check}
/>
)}
/>
) : (
<div style={{ paddingRight: 24 }}>
{value || ' '}
<Icon
type="edit"
className="editable-cell-icon"
onClick={this.edit}
/>
</div>
)
}
</div>
<td ref={node => (this.cell = node)} {...restProps}>
{editable ? (
<EditableContext.Consumer>
{(form) => {
this.form = form;
return (
editing ? (
<FormItem style={{ margin: 0 }}>
{form.getFieldDecorator(dataIndex, {
rules: [{
required: true,
message: `${title} is required.`,
}],
initialValue: record[dataIndex],
})(
<Input
ref={node => (this.input = node)}
onPressEnter={this.save}
/>
)}
</FormItem>
) : (
<div
className="editable-cell-value-wrap"
style={{ paddingRight: 24 }}
onClick={this.toggleEdit}
>
{restProps.children}
</div>
)
);
}}
</EditableContext.Consumer>
) : restProps.children}
</td>
);
}
}
@ -79,12 +129,7 @@ class EditableTable extends React.Component {
title: 'name',
dataIndex: 'name',
width: '30%',
render: (text, record) => (
<EditableCell
value={text}
onChange={this.onCellChange(record.key, 'name')}
/>
),
editable: true,
}, {
title: 'age',
dataIndex: 'age',
@ -98,7 +143,7 @@ class EditableTable extends React.Component {
return (
this.state.dataSource.length > 1
? (
<Popconfirm title="Sure to delete?" onConfirm={() => this.onDelete(record.key)}>
<Popconfirm title="Sure to delete?" onConfirm={() => this.handleDelete(record.key)}>
<a href="javascript:;">Delete</a>
</Popconfirm>
) : null
@ -122,18 +167,7 @@ class EditableTable extends React.Component {
};
}
onCellChange = (key, dataIndex) => {
return (value) => {
const dataSource = [...this.state.dataSource];
const target = dataSource.find(item => item.key === key);
if (target) {
target[dataIndex] = value;
this.setState({ dataSource });
}
};
}
onDelete = (key) => {
handleDelete = (key) => {
const dataSource = [...this.state.dataSource];
this.setState({ dataSource: dataSource.filter(item => item.key !== key) });
}
@ -152,15 +186,52 @@ class EditableTable extends React.Component {
});
}
handleSave = (row) => {
const newData = [...this.state.dataSource];
const index = newData.findIndex(item => row.key === item.key);
const item = newData[index];
newData.splice(index, 1, {
...item,
...row,
});
this.setState({ dataSource: newData });
}
render() {
const { dataSource } = this.state;
const columns = this.columns;
const components = {
body: {
row: EditableFormRow,
cell: EditableCell,
},
};
const columns = this.columns.map((col) => {
if (!col.editable) {
return col;
}
return {
...col,
onCell: record => ({
record,
editable: col.editable,
dataIndex: col.dataIndex,
title: col.title,
handleSave: this.handleSave,
}),
};
});
return (
<div>
<Button onClick={this.handleAdd} type="primary" style={{ marginBottom: 16 }}>
Add a row
</Button>
<Table bordered dataSource={dataSource} columns={columns} />
<Table
components={components}
rowClassName={() => 'editable-row'}
bordered
dataSource={dataSource}
columns={columns}
/>
</div>
);
}
@ -174,26 +245,14 @@ ReactDOM.render(<EditableTable />, mountNode);
position: relative;
}
.editable-cell-icon,
.editable-cell-icon-check {
.editable-cell-value-wrap {
padding: 5px 12px;
cursor: pointer;
}
.editable-cell-icon {
line-height: 14px;
position: absolute;
right: 0;
top: 50%;
margin-top: -7px;
display: none;
}
td:hover .editable-cell-icon {
display: inline-block;
}
.editable-cell-icon:hover,
.editable-cell-icon-check:hover {
color: #108ee9;
.editable-row:hover .editable-cell-value-wrap {
border: 1px solid #d9d9d9;
border-radius: 4px;
padding: 4px 11px;
}
````

View File

@ -1,164 +1,74 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Tabs tabPosition remove card 1`] = `
<Tabs
hideAdd={false}
prefixCls="ant-tabs"
tabBarExtraContent="xxx"
tabPosition="left"
<div
class="ant-tabs ant-tabs-left ant-tabs-vertical ant-tabs-line"
>
<Tabs
className="ant-tabs-vertical ant-tabs-line"
destroyInactiveTabPane={false}
hideAdd={false}
onChange={[Function]}
prefixCls="ant-tabs"
renderTabBar={[Function]}
renderTabContent={[Function]}
style={Object {}}
tabBarExtraContent="xxx"
tabBarPosition="left"
tabPosition="left"
<div
class="ant-tabs-bar"
role="tablist"
tabindex="0"
>
<div
className="ant-tabs ant-tabs-left ant-tabs-vertical ant-tabs-line"
style={Object {}}
class="ant-tabs-nav-container"
>
<ScrollableInkTabBar
activeKey="1"
extraContent={
<div
className="ant-tabs-extra-content"
>
xxx
</div>
}
inkBarAnimated={true}
key="tabBar"
onKeyDown={[Function]}
onNextClick={[Function]}
onPrevClick={[Function]}
onTabClick={[Function]}
panels={
<TabPane
placeholder={null}
tab="foo"
>
foo
</TabPane>
}
prefixCls="ant-tabs"
scrollAnimated={true}
styles={Object {}}
tabBarPosition="left"
<span
class="ant-tabs-tab-prev ant-tabs-tab-btn-disabled"
unselectable="unselectable"
>
<span
class="ant-tabs-tab-prev-icon"
/>
</span>
<span
class="ant-tabs-tab-next ant-tabs-tab-btn-disabled"
unselectable="unselectable"
>
<span
class="ant-tabs-tab-next-icon"
/>
</span>
<div
class="ant-tabs-nav-wrap"
>
<div
className="ant-tabs-bar"
onKeyDown={[Function]}
role="tablist"
tabIndex="0"
class="ant-tabs-nav-scroll"
>
<div
className="ant-tabs-nav-container"
key="content"
>
<span
className="ant-tabs-tab-prev ant-tabs-tab-btn-disabled"
onClick={null}
onTransitionEnd={[Function]}
unselectable="unselectable"
>
<span
className="ant-tabs-tab-prev-icon"
/>
</span>
<span
className="ant-tabs-tab-next ant-tabs-tab-btn-disabled"
onClick={null}
unselectable="unselectable"
>
<span
className="ant-tabs-tab-next-icon"
/>
</span>
<div
className="ant-tabs-nav-wrap"
>
<div
className="ant-tabs-nav-scroll"
>
<div
className="ant-tabs-nav ant-tabs-nav-animated"
>
<div
className="ant-tabs-ink-bar ant-tabs-ink-bar-animated"
key="inkBar"
/>
<div
aria-disabled="false"
aria-selected="true"
className="ant-tabs-tab-active ant-tabs-tab"
key="1"
onClick={[Function]}
role="tab"
style={
Object {
"marginRight": undefined,
}
}
>
foo
</div>
</div>
</div>
</div>
</div>
<div
className="ant-tabs-extra-content"
key="extra"
style={Object {}}
>
xxx
</div>
</div>
</ScrollableInkTabBar>
<TabContent
activeKey="1"
animated={true}
animatedWithMargin={true}
destroyInactiveTabPane={false}
key="tabContent"
onChange={[Function]}
prefixCls="ant-tabs"
tabBarPosition="left"
>
<div
className="ant-tabs-content ant-tabs-content-animated"
style={
Object {
"marginTop": "0%",
}
}
>
<TabPane
active={true}
destroyInactiveTabPane={false}
key="1"
placeholder={null}
rootPrefixCls="ant-tabs"
tab="foo"
class="ant-tabs-nav ant-tabs-nav-animated"
>
<div
aria-hidden="false"
className="ant-tabs-tabpane ant-tabs-tabpane-active"
role="tabpanel"
class="ant-tabs-ink-bar ant-tabs-ink-bar-animated"
/>
<div
aria-disabled="false"
aria-selected="true"
class="ant-tabs-tab-active ant-tabs-tab"
role="tab"
>
foo
</div>
</TabPane>
</div>
</div>
</TabContent>
</div>
</div>
</Tabs>
</Tabs>
<div
class="ant-tabs-extra-content"
>
xxx
</div>
</div>
<div
class="ant-tabs-content ant-tabs-content-animated"
style="margin-top:0%"
>
<div
aria-hidden="false"
class="ant-tabs-tabpane ant-tabs-tabpane-active"
role="tabpanel"
>
foo
</div>
</div>
</div>
`;

View File

@ -1,5 +1,5 @@
import React from 'react';
import { mount } from 'enzyme';
import { mount, render } from 'enzyme';
import Tabs from '..';
const { TabPane } = Tabs;
@ -31,7 +31,7 @@ describe('Tabs', () => {
describe('tabPosition', () => {
it('remove card', () => {
const wrapper = mount(
const wrapper = render(
<Tabs tabPosition="left" tabBarExtraContent="xxx">
<TabPane tab="foo" key="1">foo</TabPane>
</Tabs>

View File

@ -77,6 +77,8 @@ export interface TreeProps {
checkStrictly?: boolean;
/** 是否支持选中 */
checkable?: boolean;
/** 是否禁用树 */
disabled?: boolean;
/** 默认展开所有树节点 */
defaultExpandAll?: boolean;
/** 默认展开对应树节点 */

View File

@ -268,9 +268,9 @@ We have completed a simple application, but you may still have lots of questions
You can:
- Visit [dva official website](https://github.com/dvajs/dva).
- Be familiar with the [8 Concepts](https://github.com/dvajs/dva/blob/master/docs/Concepts.md), and understand how they are connected together
- Know all [dva APIs](https://github.com/dvajs/dva/blob/master/docs/API.md)
- Checkout [dva knowledgemap](https://github.com/dvajs/dva-knowledgemap), including all the basic knowledge with ES6, React, dva
- Visit [dva official website](https://dvajs.com/).
- Be familiar with the [8 Concepts](https://dvajs.com/guide/concepts.html), and understand how they are connected together
- Know all [dva APIs](https://dvajs.com/api/)
- Checkout [dva knowledgemap](https://dvajs.com/knowledgemap/), including all the basic knowledge with ES6, React, dva
- Checkout [more FAQ](https://github.com/dvajs/dva/issues?q=is%3Aissue+is%3Aclosed+label%3Afaq)
- If your project is created with [dva-cli](https://github.com/dvajs/dva-cli) , checkout how to [Configure it](https://github.com/sorrycc/roadhog#configuration)

View File

@ -270,9 +270,9 @@ File sizes after gzip:
你可以:
- 访问 [dva 官网](https://github.com/dvajs/dva)
- 理解 dva 的 [8 个概念](https://github.com/dvajs/dva/blob/master/docs/Concepts_zh-CN.md) ,以及他们是如何串起来的
- 掌握 dva 的[所有 API](https://github.com/dvajs/dva/blob/master/docs/API_zh-CN.md)
- 查看 [dva 知识地图](https://github.com/dvajs/dva-knowledgemap) ,包含 ES6, React, dva 等所有基础知识
- 访问 [dva 官网](https://dvajs.com/)
- 理解 dva 的 [8 个概念](https://dvajs.com/guide/concepts.html) ,以及他们是如何串起来的
- 掌握 dva 的[所有 API](https://dvajs.com/api/)
- 查看 [dva 知识地图](https://dvajs.com/knowledgemap/) ,包含 ES6, React, dva 等所有基础知识
- 查看 [更多 FAQ](https://github.com/dvajs/dva/issues?q=is%3Aissue+is%3Aclosed+label%3Afaq),看看别人通常会遇到什么问题
- 如果你基于 dva-cli 创建项目,最好了解他的 [配置方式](https://github.com/sorrycc/roadhog/blob/master/README_zh-cn.md#配置)

View File

@ -90,11 +90,11 @@ $ yarn add react-app-rewired --dev
```diff
/* package.json */
"scripts": {
- "start": "react-scripts start",
- "start": "react-scripts-ts start",
+ "start": "react-app-rewired start --scripts-version react-scripts-ts",
- "build": "react-scripts build",
- "build": "react-scripts-ts build",
+ "build": "react-app-rewired build --scripts-version react-scripts-ts",
- "test": "react-scripts test --env=jsdom",
- "test": "react-scripts-ts test --env=jsdom",
+ "test": "react-app-rewired test --env=jsdom --scripts-version react-scripts-ts",
}
```

View File

@ -89,11 +89,11 @@ $ yarn add react-app-rewired --dev
```diff
/* package.json */
"scripts": {
- "start": "react-scripts start",
- "start": "react-scripts-ts start",
+ "start": "react-app-rewired start --scripts-version react-scripts-ts",
- "build": "react-scripts build",
- "build": "react-scripts-ts build",
+ "build": "react-app-rewired build --scripts-version react-scripts-ts",
- "test": "react-scripts test --env=jsdom",
- "test": "react-scripts-ts test --env=jsdom",
+ "test": "react-app-rewired test --env=jsdom --scripts-version react-scripts-ts",
}
```

11
tests/__mocks__/react.js vendored Normal file
View File

@ -0,0 +1,11 @@
const React = require.requireActual('react');
if (!React.createContext) {
React.createContext = () => {
const Provider = ({ children }) => children;
const Consumer = ({ children }) => children();
return { Provider, Consumer };
};
}
module.exports = React;