Skip to content

Instantly share code, notes, and snippets.

@jviereck
Created March 19, 2015 17:21
Show Gist options
  • Save jviereck/9a71734afcfe848ddbe2 to your computer and use it in GitHub Desktop.
Save jviereck/9a71734afcfe848ddbe2 to your computer and use it in GitHub Desktop.
'use strict';
var React = require('react');
// EXAMPLE:
//
// var ExampleComponent = React.createClass({
// render(): any {
// // Define the CSS content used by this component.
// var styleContent = `
// .chunkTitle {
// background: lightgray;
// margin-bottom: 4px;
// padding: 2px;
// }`;
// // By using a <StyleDef content="cssContent" /> the CSS definitions get
// // added within an <style>cssContent</style> in the header of the page.
// return (
// <div className="chunkTitle">
// <StyleDef content={styleContent} />
// ContentGoesHere.
// </div>
// );
// }
// });
// Way to define CSS styles in React components that appear as real <styles>
// on the page instead of using the `styles` property.
// Defining the CSS string directly inside of a <style> tag does not work as
// the parser used by babel.js rejects CSS text like "2px" as invalid JS. Also,
// the placeholder like `{someVar}` causes problems with the usage of brakets
// in a CSS definition like `.class { color: red }`, where the content between
// the brackets should not be replaced by a variable.
// The CSS content is defined with the helf of a react component <StyleDef />
// where the actual CSS content is defined as the `content="..."` property.
// Instead of creating a <style> element on the page per <StyleDef /> component,
// only one <style> element per unique CSS content is created. Reference counting
// is used to determine if the CSS content is no longer used in th app and the
// corresponding <style> can be removed from the page again.
// List of all the physical styles currently mounted in the document's <head>.
var mountedDomStyles = [];
var DOMStyle = function(content) {
this.content = content;
this.refCounter = 1;
// Create the actual style element and mount it in the document's <head>.
this.dom = document.createElement('style');
this.dom.textContent = content;
document.head.appendChild(this.dom);
}
var incrStyleContent = function(content) {
for (var i = 0; i < mountedDomStyles.length; i++) {
if (mountedDomStyles[i].content === content) {
mountedDomStyles[i].refCounter += 1;
return;
}
}
mountedDomStyles.push(new DOMStyle(content));
}
var decrStyleContent = function(content) {
for (var i = 0; i < mountedDomStyles.length; i++) {
if (mountedDomStyles[i] === content) {
if ((mountedDomStyles[i].refCounter -= 1) == 0) {
document.head.remove(mountedDomStyles[i].dom);
mountedDomStyles.splice(i, 1);
return;
}
}
}
}
var StyleDef = React.createClass({
componentDidMount: function() {
incrStyleContent(this.props.content);
},
componentDidUpdate: function(nextProps) {
if (nextProps.content !== this.props.content) {
decrStyleContent(this.props.content);
incrStyleContent(nextProps.content);
}
},
componentDidUnmount: function() {
decrStyleContent(this.props.content);
},
render(): any {
// The <StyleDef> itself should not appear in the DOM.
return null;
}
});
module.exports = {
StyleDef: StyleDef
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment