Skip to content

Commit

Permalink
feat: make Notification.newInstance async, close: #21 (#27)
Browse files Browse the repository at this point in the history
  • Loading branch information
benjycui authored Oct 10, 2017
1 parent 3d1d2b7 commit 4b44f2e
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 107 deletions.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,16 @@ online example: http://react-component.github.io/notification/examples/

```js
var Notification = require('rc-notification');
var notification = Notification.newInstance();
notification.notice({
content: 'content'
Notification.newInstance({}, notification => {
notification.notice({
content: 'content'
});
});
```

## API

### Notification.newInstance(props)
### Notification.newInstance(props, (notification) => void) => void

props details:

Expand Down
3 changes: 2 additions & 1 deletion examples/simple.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import 'rc-notification/assets/index.less';
import Notification from 'rc-notification';
import React from 'react';
import ReactDOM from 'react-dom';
const notification = Notification.newInstance({});
let notification = null;
Notification.newInstance({}, (n) => notification = n);

function simpleFn() {
notification.notice({
Expand Down
41 changes: 24 additions & 17 deletions src/Notification.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class Notification extends Component {
}
}

Notification.newInstance = function newNotificationInstance(properties) {
Notification.newInstance = function newNotificationInstance(properties, callback) {
const { getContainer, ...props } = properties || {};
let div;
if (getContainer) {
Expand All @@ -96,22 +96,29 @@ Notification.newInstance = function newNotificationInstance(properties) {
div = document.createElement('div');
document.body.appendChild(div);
}
const notification = ReactDOM.render(<Notification {...props} />, div);
return {
notice(noticeProps) {
notification.add(noticeProps);
},
removeNotice(key) {
notification.remove(key);
},
component: notification,
destroy() {
ReactDOM.unmountComponentAtNode(div);
if (!getContainer) {
document.body.removeChild(div);
}
},
};
let called = false;
function ref(notification) {
if (called) {
return;
}
called = true;
callback({

This comment has been minimized.

Copy link
@yesmeck

yesmeck Oct 30, 2017

Member

@benjycui 是不是要判断下 callback 是否存在?

This comment has been minimized.

Copy link
@benjycui

benjycui Oct 30, 2017

Author Member

感觉不需要判断,因为在这里 callback 不是可选的,因为如果没有 callback,用户拿不到实例,就没意义了。

This comment has been minimized.

Copy link
@yesmeck

yesmeck Oct 30, 2017

Member

嗯,刚才是碰到的是另外一个问题,同时安装 antd@2 和 antd-mobile@2, antd 里会 require 到 rc-notification@3。

This comment has been minimized.

Copy link
@benjycui

benjycui Oct 30, 2017

Author Member

@paranoidjk antd-mobile 的 rc-notification 要升级一下?不然应该兼容不了 react 16

This comment has been minimized.

Copy link
@yesmeck

yesmeck Oct 30, 2017

Member

我看 antd-mobile@2 已经升了

notice(noticeProps) {
notification.add(noticeProps);
},
removeNotice(key) {
notification.remove(key);
},
component: notification,
destroy() {
ReactDOM.unmountComponentAtNode(div);
if (!getContainer) {
document.body.removeChild(div);
}
},
});
}
ReactDOM.render(<Notification {...props} ref={ref} />, div);
};

export default Notification;
215 changes: 130 additions & 85 deletions tests/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'core-js/es6/map';
import 'core-js/es6/set';
import React from 'react';
import ReactDOM from 'react-dom';
import TestUtils from 'react-dom/test-utils';
import expect from 'expect.js';

Expand All @@ -10,117 +11,161 @@ require('../assets/index.less');

describe('rc-notification', () => {
it('works', (done) => {
const notification = Notification.newInstance();
notification.notice({
content: <p className="test">1</p>,
duration: 0.1,
Notification.newInstance({}, notification => {
notification.notice({
content: <p className="test">1</p>,
duration: 0.1,
});
setTimeout(() => {
expect(
TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test').length
).to.be(1);
}, 10);
setTimeout(() => {
expect(
TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test').length
).to.be(0);
notification.destroy();
done();
}, 1000);
});
expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component,
'test').length).to.be(1);
setTimeout(() => {
expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component,
'test').length).to.be(0);
notification.destroy();
done();
}, 1000);
});

it('works with multi instance', (done) => {
const notification = Notification.newInstance();
notification.notice({
content: <p className="test">1</p>,
duration: 0.1,
});
notification.notice({
content: <p className="test">2</p>,
duration: 0.1,
Notification.newInstance({}, notification => {
notification.notice({
content: <p className="test">1</p>,
duration: 0.1,
});
notification.notice({
content: <p className="test">2</p>,
duration: 0.1,
});
setTimeout(() => {
expect(
TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test').length
).to.be(2);
}, 10);
setTimeout(() => {
expect(
TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test').length
).to.be(0);
notification.destroy();
done();
}, 1000);
});
expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component,
'test').length).to.be(2);
setTimeout(() => {
expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component,
'test').length).to.be(0);
notification.destroy();
done();
}, 1000);
});

it('destroy works', () => {
const notification = Notification.newInstance();
notification.notice({
content: <p id="test" className="test">222222</p>,
duration: 0.1,
Notification.newInstance({}, notification => {
notification.notice({
content: <p id="test" className="test">222222</p>,
duration: 0.1,
});
setTimeout(() => {
expect(
TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test').length
).to.be(1);
notification.destroy();
expect(document.getElementById('test')).not.to.be.ok();
}, 10);
});
expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component,
'test').length).to.be(1);
notification.destroy();
expect(document.getElementById('test')).not.to.be.ok();
});

it('getContainer works', () => {
const notification = Notification.newInstance({
Notification.newInstance({
getContainer: () => {
const div = document.createElement('div');
div.className = 'rc';
document.body.appendChild(div);
return div;
},
}, notification => {
notification.notice({
content: <p id="test" className="test">222222</p>,
duration: 1,
});
expect(document.querySelectorAll('.rc').length).to.be(1);
notification.destroy();
});
notification.notice({
content: <p id="test" className="test">222222</p>,
duration: 1,
});
expect(document.querySelectorAll('.rc').length).to.be(1);
notification.destroy();
});

it('remove notify works', (done) => {
const notification = Notification.newInstance();
const key = Date.now();
const close = (k) => {
notification.removeNotice(k);
};
notification.notice({
content: <p id="test" className="test">
<button id="closeButton" onClick={close.bind(null, key)}>
close
</button>
</p>,
key,
duration: null,
});
Notification.newInstance({}, notification => {
const key = Date.now();
const close = (k) => {
notification.removeNotice(k);
};
notification.notice({
content: <p className="test">
<button id="closeButton" onClick={close.bind(null, key)}>
close
</button>
</p>,
key,
duration: null,
});

expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test')
.length).to.be(1);
const btnClose = document.getElementById('closeButton');
TestUtils.Simulate.click(btnClose);
setTimeout(() => {
expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test')
.length).to.be(0);
notification.destroy();
done();
}, 1000);
setTimeout(() => {
expect(
TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test').length
).to.be(1);
const btnClose = document.getElementById('closeButton');
TestUtils.Simulate.click(btnClose);
setTimeout(() => {
expect(
TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test').length
).to.be(0);
notification.destroy();
done();
}, 1000);
}, 10);
});
});

it('freeze notification layer when mouse over', (done) => {
const notification = Notification.newInstance();
notification.notice({
content: <p id="freeze" className="freeze">freeze</p>,
duration: 0.3,
});
expect(document.querySelectorAll('.freeze').length).to.be(1);
const content = document.getElementById('freeze');
TestUtils.Simulate.mouseEnter(content);
setTimeout(() => {
expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'freeze')
.length).to.be(1);
TestUtils.Simulate.mouseLeave(content);
Notification.newInstance({}, notification => {
notification.notice({
content: <p id="freeze" className="freeze">freeze</p>,
duration: 0.3,
});
setTimeout(() => {
expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'freeze')
.length).to.be(0);
notification.destroy();
done();
}, 400);
}, 500);
expect(document.querySelectorAll('.freeze').length).to.be(1);
const content = document.getElementById('freeze');
TestUtils.Simulate.mouseEnter(content);
setTimeout(() => {
expect(
TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'freeze').length
).to.be(1);
TestUtils.Simulate.mouseLeave(content);
setTimeout(() => {
expect(
TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'freeze').length
).to.be(0);
notification.destroy();
done();
}, 400);
}, 500);
}, 10);
});
});

it('should work in lifecycle of React component', () => {
class Test extends React.Component {
componentDidMount() {
Notification.newInstance({}, notification => {
notification.notice({
content: <span>In lifecycle</span>,
});
});
}
render() {
return null;
}
}
const container = document.createElement('div');
document.body.appendChild(container);
expect(() => ReactDOM.render(<Test />, container))
.to.not.throwException();
});
});

0 comments on commit 4b44f2e

Please sign in to comment.