Skip to content

Instantly share code, notes, and snippets.

@brigand
Last active November 6, 2019 05:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brigand/2da6be4df920eb1e9acff8fa98b57e22 to your computer and use it in GitHub Desktop.
Save brigand/2da6be4df920eb1e9acff8fa98b57e22 to your computer and use it in GitHub Desktop.
Basic implementation of !important styles for React
class Styled extends React.Component {
static counter = 1e9;
id = `__styled__${Styled.counter++}`;
componentDidMount() {
this.apply();
}
componentDidUpdate(prevProps, prevState) {
const anyChanged = Object.entries({
...prevProps.style,
...this.props.style
}).some(([k, v]) => {
return v !== prevProps.style[k];
});
if (!anyChanged) {
return;
}
this.apply();
}
apply() {
const {
el,
props: { style }
} = this;
el.id = this.id;
el.sheet.insertRule(`#${this.id} + * {}`);
const index = el.sheet.rules.length - 1;
Object.entries(style).forEach(([k, v]) => {
if (typeof v === 'number') {
v = String(v) + 'px';
}
if (!v) {
return;
}
const k2 = k.replace(/([A-Z])/g, '-$1');
const v2 = v.replace(/\s+!important\s*$/, '');
if (v !== v2) {
el.sheet.rules[index].style.setProperty(k2, v2, 'important');
} else {
el.sheet.rules[index].style.setProperty(k2, v2);
}
});
if (index > 0) {
el.sheet.removeRule(0);
}
}
render() {
return (
<React.Fragment>
<style
ref={el => {
this.el = el;
}}
/>
{this.props.children}
</React.Fragment>
);
}
}
class App extends React.Component {
state = {
hue: 0,
start: Date.now(),
frames: 0
};
componentDidMount() {
let last;
const tick = time => {
const diff = time - (last || time - 16);
last = time;
this.setState(
{
hue: (this.state.hue + diff * 0.05) % 360,
frames: this.state.frames + 1
},
() => requestAnimationFrame(tick)
);
};
requestAnimationFrame(tick);
}
render() {
return (
<div className="App">
<h1>Simple Styled</h1>
<Styled
style={{
background: `hsl(${this.state.hue}, 92%, 32%) !important`,
color: 'pink'
}}
>
<div
style={{ background: 'purple', color: 'white', padding: '6em 0' }}
>
{Math.round(
(this.state.frames * 1000) / (Date.now() - this.state.start)
)}fps
</div>
</Styled>
</div>
);
}
}
const rootElement = document.getElementById('root');
ReactDOM.render(<App />, rootElement);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment