Skip to content

Commit 4b44f2e

Browse files
authored
feat: make Notification.newInstance async, close: #21 (#27)
1 parent 3d1d2b7 commit 4b44f2e

File tree

4 files changed

+161
-107
lines changed

4 files changed

+161
-107
lines changed

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,16 @@ online example: http://react-component.github.io/notification/examples/
5151

5252
```js
5353
var Notification = require('rc-notification');
54-
var notification = Notification.newInstance();
55-
notification.notice({
56-
content: 'content'
54+
Notification.newInstance({}, notification => {
55+
notification.notice({
56+
content: 'content'
57+
});
5758
});
5859
```
5960

6061
## API
6162

62-
### Notification.newInstance(props)
63+
### Notification.newInstance(props, (notification) => void) => void
6364

6465
props details:
6566

examples/simple.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import 'rc-notification/assets/index.less';
33
import Notification from 'rc-notification';
44
import React from 'react';
55
import ReactDOM from 'react-dom';
6-
const notification = Notification.newInstance({});
6+
let notification = null;
7+
Notification.newInstance({}, (n) => notification = n);
78

89
function simpleFn() {
910
notification.notice({

src/Notification.jsx

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ class Notification extends Component {
8787
}
8888
}
8989

90-
Notification.newInstance = function newNotificationInstance(properties) {
90+
Notification.newInstance = function newNotificationInstance(properties, callback) {
9191
const { getContainer, ...props } = properties || {};
9292
let div;
9393
if (getContainer) {
@@ -96,22 +96,29 @@ Notification.newInstance = function newNotificationInstance(properties) {
9696
div = document.createElement('div');
9797
document.body.appendChild(div);
9898
}
99-
const notification = ReactDOM.render(<Notification {...props} />, div);
100-
return {
101-
notice(noticeProps) {
102-
notification.add(noticeProps);
103-
},
104-
removeNotice(key) {
105-
notification.remove(key);
106-
},
107-
component: notification,
108-
destroy() {
109-
ReactDOM.unmountComponentAtNode(div);
110-
if (!getContainer) {
111-
document.body.removeChild(div);
112-
}
113-
},
114-
};
99+
let called = false;
100+
function ref(notification) {
101+
if (called) {
102+
return;
103+
}
104+
called = true;
105+
callback({
106+
notice(noticeProps) {
107+
notification.add(noticeProps);
108+
},
109+
removeNotice(key) {
110+
notification.remove(key);
111+
},
112+
component: notification,
113+
destroy() {
114+
ReactDOM.unmountComponentAtNode(div);
115+
if (!getContainer) {
116+
document.body.removeChild(div);
117+
}
118+
},
119+
});
120+
}
121+
ReactDOM.render(<Notification {...props} ref={ref} />, div);
115122
};
116123

117124
export default Notification;

tests/index.js

Lines changed: 130 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'core-js/es6/map';
22
import 'core-js/es6/set';
33
import React from 'react';
4+
import ReactDOM from 'react-dom';
45
import TestUtils from 'react-dom/test-utils';
56
import expect from 'expect.js';
67

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

1112
describe('rc-notification', () => {
1213
it('works', (done) => {
13-
const notification = Notification.newInstance();
14-
notification.notice({
15-
content: <p className="test">1</p>,
16-
duration: 0.1,
14+
Notification.newInstance({}, notification => {
15+
notification.notice({
16+
content: <p className="test">1</p>,
17+
duration: 0.1,
18+
});
19+
setTimeout(() => {
20+
expect(
21+
TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test').length
22+
).to.be(1);
23+
}, 10);
24+
setTimeout(() => {
25+
expect(
26+
TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test').length
27+
).to.be(0);
28+
notification.destroy();
29+
done();
30+
}, 1000);
1731
});
18-
expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component,
19-
'test').length).to.be(1);
20-
setTimeout(() => {
21-
expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component,
22-
'test').length).to.be(0);
23-
notification.destroy();
24-
done();
25-
}, 1000);
2632
});
2733

2834
it('works with multi instance', (done) => {
29-
const notification = Notification.newInstance();
30-
notification.notice({
31-
content: <p className="test">1</p>,
32-
duration: 0.1,
33-
});
34-
notification.notice({
35-
content: <p className="test">2</p>,
36-
duration: 0.1,
35+
Notification.newInstance({}, notification => {
36+
notification.notice({
37+
content: <p className="test">1</p>,
38+
duration: 0.1,
39+
});
40+
notification.notice({
41+
content: <p className="test">2</p>,
42+
duration: 0.1,
43+
});
44+
setTimeout(() => {
45+
expect(
46+
TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test').length
47+
).to.be(2);
48+
}, 10);
49+
setTimeout(() => {
50+
expect(
51+
TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test').length
52+
).to.be(0);
53+
notification.destroy();
54+
done();
55+
}, 1000);
3756
});
38-
expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component,
39-
'test').length).to.be(2);
40-
setTimeout(() => {
41-
expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component,
42-
'test').length).to.be(0);
43-
notification.destroy();
44-
done();
45-
}, 1000);
4657
});
4758

4859
it('destroy works', () => {
49-
const notification = Notification.newInstance();
50-
notification.notice({
51-
content: <p id="test" className="test">222222</p>,
52-
duration: 0.1,
60+
Notification.newInstance({}, notification => {
61+
notification.notice({
62+
content: <p id="test" className="test">222222</p>,
63+
duration: 0.1,
64+
});
65+
setTimeout(() => {
66+
expect(
67+
TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test').length
68+
).to.be(1);
69+
notification.destroy();
70+
expect(document.getElementById('test')).not.to.be.ok();
71+
}, 10);
5372
});
54-
expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component,
55-
'test').length).to.be(1);
56-
notification.destroy();
57-
expect(document.getElementById('test')).not.to.be.ok();
5873
});
5974

6075
it('getContainer works', () => {
61-
const notification = Notification.newInstance({
76+
Notification.newInstance({
6277
getContainer: () => {
6378
const div = document.createElement('div');
6479
div.className = 'rc';
6580
document.body.appendChild(div);
6681
return div;
6782
},
83+
}, notification => {
84+
notification.notice({
85+
content: <p id="test" className="test">222222</p>,
86+
duration: 1,
87+
});
88+
expect(document.querySelectorAll('.rc').length).to.be(1);
89+
notification.destroy();
6890
});
69-
notification.notice({
70-
content: <p id="test" className="test">222222</p>,
71-
duration: 1,
72-
});
73-
expect(document.querySelectorAll('.rc').length).to.be(1);
74-
notification.destroy();
7591
});
7692

7793
it('remove notify works', (done) => {
78-
const notification = Notification.newInstance();
79-
const key = Date.now();
80-
const close = (k) => {
81-
notification.removeNotice(k);
82-
};
83-
notification.notice({
84-
content: <p id="test" className="test">
85-
<button id="closeButton" onClick={close.bind(null, key)}>
86-
close
87-
</button>
88-
</p>,
89-
key,
90-
duration: null,
91-
});
94+
Notification.newInstance({}, notification => {
95+
const key = Date.now();
96+
const close = (k) => {
97+
notification.removeNotice(k);
98+
};
99+
notification.notice({
100+
content: <p className="test">
101+
<button id="closeButton" onClick={close.bind(null, key)}>
102+
close
103+
</button>
104+
</p>,
105+
key,
106+
duration: null,
107+
});
92108

93-
expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test')
94-
.length).to.be(1);
95-
const btnClose = document.getElementById('closeButton');
96-
TestUtils.Simulate.click(btnClose);
97-
setTimeout(() => {
98-
expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test')
99-
.length).to.be(0);
100-
notification.destroy();
101-
done();
102-
}, 1000);
109+
setTimeout(() => {
110+
expect(
111+
TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test').length
112+
).to.be(1);
113+
const btnClose = document.getElementById('closeButton');
114+
TestUtils.Simulate.click(btnClose);
115+
setTimeout(() => {
116+
expect(
117+
TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'test').length
118+
).to.be(0);
119+
notification.destroy();
120+
done();
121+
}, 1000);
122+
}, 10);
123+
});
103124
});
104125

105126
it('freeze notification layer when mouse over', (done) => {
106-
const notification = Notification.newInstance();
107-
notification.notice({
108-
content: <p id="freeze" className="freeze">freeze</p>,
109-
duration: 0.3,
110-
});
111-
expect(document.querySelectorAll('.freeze').length).to.be(1);
112-
const content = document.getElementById('freeze');
113-
TestUtils.Simulate.mouseEnter(content);
114-
setTimeout(() => {
115-
expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'freeze')
116-
.length).to.be(1);
117-
TestUtils.Simulate.mouseLeave(content);
127+
Notification.newInstance({}, notification => {
128+
notification.notice({
129+
content: <p id="freeze" className="freeze">freeze</p>,
130+
duration: 0.3,
131+
});
118132
setTimeout(() => {
119-
expect(TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'freeze')
120-
.length).to.be(0);
121-
notification.destroy();
122-
done();
123-
}, 400);
124-
}, 500);
133+
expect(document.querySelectorAll('.freeze').length).to.be(1);
134+
const content = document.getElementById('freeze');
135+
TestUtils.Simulate.mouseEnter(content);
136+
setTimeout(() => {
137+
expect(
138+
TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'freeze').length
139+
).to.be(1);
140+
TestUtils.Simulate.mouseLeave(content);
141+
setTimeout(() => {
142+
expect(
143+
TestUtils.scryRenderedDOMComponentsWithClass(notification.component, 'freeze').length
144+
).to.be(0);
145+
notification.destroy();
146+
done();
147+
}, 400);
148+
}, 500);
149+
}, 10);
150+
});
151+
});
152+
153+
it('should work in lifecycle of React component', () => {
154+
class Test extends React.Component {
155+
componentDidMount() {
156+
Notification.newInstance({}, notification => {
157+
notification.notice({
158+
content: <span>In lifecycle</span>,
159+
});
160+
});
161+
}
162+
render() {
163+
return null;
164+
}
165+
}
166+
const container = document.createElement('div');
167+
document.body.appendChild(container);
168+
expect(() => ReactDOM.render(<Test />, container))
169+
.to.not.throwException();
125170
});
126171
});

0 commit comments

Comments
 (0)