Skip to content

Commit

Permalink
[NoSrr] Add a defer property
Browse files Browse the repository at this point in the history
  • Loading branch information
oliviertassinari committed Aug 9, 2018
1 parent c937ab0 commit 608bb3d
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 6 deletions.
35 changes: 31 additions & 4 deletions packages/material-ui/src/NoSsr/NoSsr.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import React from 'react';
import PropTypes from 'prop-types';
import exactProp from '../utils/exactProp';

const Fallback = () => null;

/**
* NoSsr purposely removes components from the subject of Server Side Rendering (SSR).
*
Expand All @@ -19,7 +17,27 @@ class NoSsr extends React.Component {
};

componentDidMount() {
this.setState({ mounted: true }); // eslint-disable-line react/no-did-mount-set-state
this.mounted = true;

if (this.props.defer) {
// Wondering why we use two raf? Check this video out:
// https://www.youtube.com/watch?v=cCOL7MC4Pl0
requestAnimationFrame(() => {
// The browser should be about to render the DOM that React commited at this point.
// We don't want to interrupt. Let's wait the next raf.
requestAnimationFrame(() => {
if (this.mounted) {
this.setState({ mounted: true });
}
});
});
} else {
this.setState({ mounted: true }); // eslint-disable-line react/no-did-mount-set-state
}
}

componentWillUnmount() {
this.mounted = false;
}

render() {
Expand All @@ -31,13 +49,22 @@ class NoSsr extends React.Component {

NoSsr.propTypes = {
children: PropTypes.node.isRequired,
/**
* If `true`, the component will not only prevent server side rendering.
* It will also defer the rendering of the children into a different screen frame.
*/
defer: PropTypes.bool,
/**
* The fallback content to display.
*/
fallback: PropTypes.node,
};

NoSsr.propTypes = exactProp(NoSsr.propTypes);

NoSsr.defaultProps = {
fallback: <Fallback />,
defer: false,
fallback: null,
};

export default NoSsr;
20 changes: 19 additions & 1 deletion packages/material-ui/src/NoSsr/NoSsr.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe('<NoSsr />', () => {
<span>Hello</span>
</NoSsr>,
);
assert.strictEqual(wrapper.name(), 'Fallback');
assert.strictEqual(wrapper.name(), null);
});
});

Expand All @@ -37,6 +37,7 @@ describe('<NoSsr />', () => {
</NoSsr>,
);
assert.strictEqual(wrapper.find('span').length, 1);
assert.strictEqual(wrapper.text(), 'Hello');
});
});

Expand All @@ -50,4 +51,21 @@ describe('<NoSsr />', () => {
assert.strictEqual(wrapper.text(), 'fallback');
});
});

describe('prop: defer', () => {
it('should defer the rendering', done => {
const wrapper = mount(
<NoSsr defer>
<span>Hello</span>
</NoSsr>,
);
assert.strictEqual(wrapper.find('span').length, 0);
setTimeout(() => {
wrapper.update();
assert.strictEqual(wrapper.find('span').length, 1);
assert.strictEqual(wrapper.text(), 'Hello');
done();
}, 100);
});
});
});
3 changes: 2 additions & 1 deletion pages/api/no-ssr.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ This component can be useful in a variety of situations:
| Name | Type | Default | Description |
|:-----|:-----|:--------|:------------|
| <span class="prop-name required">children *</span> | <span class="prop-type">node |   | |
| <span class="prop-name">fallback</span> | <span class="prop-type">node | <span class="prop-default">&lt;Fallback /></span> | |
| <span class="prop-name">defer</span> | <span class="prop-type">bool | <span class="prop-default">false</span> | If `true`, the component will not only prevent server side rendering. It will also defer the rendering of the children into a different screen frame. |
| <span class="prop-name">fallback</span> | <span class="prop-type">node | <span class="prop-default">null</span> | The fallback content to display. |

Any other properties supplied will be spread to the root element (native element).

Expand Down

0 comments on commit 608bb3d

Please sign in to comment.