<div id="root"></div>
@use postcss-cssnext;
@use postcss-simple-vars;
@use postcss-custom-media;
@use postcss-nested;
@use postcss-mixins;
@use lost;
body {
background-color: #333;
font-family: "Roboto";
}
main {
max-width: 100vw;
width: 100%;
height: 100vh;
}
button {
position: absolute;
background-color: #666;
border-radius: 5px;
color: white;
border: 0;
padding: 20px;
bottom: 50%;
left: 50%;
transform: translate(-50%, calc(50% + 100px));
font-weight: bold;
cursor: pointer;
text-transform: uppercase;
transition: 0.25s all;
&:hover {
background-color: #F07818;
}
}
ol {
list-style-type: none;
display: flex;
flex-flow: row;
width: 100%;
max-width: 500px;
padding: 0;
justify-content: space-around;
align-items: center;
height: 100%;
margin: 0 auto;
& li {
flex: 0 0 auto;
}
}
.bulb {
background-color: #888;
border-radius: 50%;
min-width: 20px;
min-height: 20px;
padding: 10px;
display: block;
text-align: center;
box-shadow: 0 2px 0 0 rgba(0, 0, 0, 0.5);
position: relative;
&.pure:before {
content: 'P';
font-weight: bold;
color: white;
}
&:after {
position: absolute;
width: 100%;
background-color: #D36112;
height: 5px;
content: '';
z-index: -1;
top: 50%;
left: 50%;
transform: translate(5px, -50%);
}
&:last-child:after {
content: none;
}
&.on {
background-color: #FCEBB6;
box-shadow: 0 0 3px 6px rgba(230,219,151, 0.4);
}
}
View Compiled
// Remove context from 'Bulb', instead pass 'areLightsOn' as a prop
const Bulb = ({ children, className, areLightsOn })=> {
const lightStateClassName = areLightsOn ? 'on' : 'off';
const classNames = `bulb ${className} ${lightStateClassName}`;
return (
<li className={classNames}>{children}</li>
);
}
// Update 'LightBulb' to take in props
class LightBulb extends React.Component {
render(){
return (
<Bulb {...this.props} />
);
}
};
// Update 'PureLightBulb' to take in props
class PureLightBulb extends React.PureComponent {
render(){
return (
<Bulb className="pure" {...this.props} />
);
}
}
// Add in our withLights Higher Order Component
const withContext = (WrappedComponent) => {
class LightsHOC extends React.Component {
// Only update when context 'areLightsOn' changes
shouldComponentUpdate(nextProps, nextState, nextContext){
return this.context.areLightsOn !== nextContext.areLightsOn;
}
render(){
// Pass in context as a prop to our `PureLightBulb' and 'LightBulb'
return <WrappedComponent {...this.props} {...this.context} />
}
}
// Define context types available on our Higher Order Component
LightsHOC.contextTypes = {
areLightsOn: React.PropTypes.bool
};
return LightsHOC;
};
// Wrap our light bulb component with our higher order component
const PureLightBulbWithContext = withContext(PureLightBulb);
const LightBulbWithContext = withContext(LightBulb);
class Wire extends React.Component {
render(){
return (
<ol>
<LightBulbWithContext />
<PureLightBulbWithContext />
<LightBulbWithContext />
<LightBulbWithContext />
<LightBulbWithContext />
<PureLightBulbWithContext />
<PureLightBulbWithContext />
<PureLightBulbWithContext />
</ol>
)
}
}
class Lights extends React.PureComponent {
constructor(props){
super(props);
this.state = {
areLightsOn: false
};
this.toggleLights = this.toggleLights.bind(this);
}
getChildContext(){
return {
areLightsOn: this.state.areLightsOn
}
}
toggleLights(){
this.setState({
areLightsOn: ! this.state.areLightsOn
});
}
render(){
return (
<main>
<Wire />
<button type="button" onClick={this.toggleLights}>
Toggle Lights
</button>
</main>
);
}
}
Lights.childContextTypes = {
areLightsOn: React.PropTypes.bool
}
ReactDOM.render(<Lights />, document.getElementById('root'));
View Compiled
This Pen doesn't use any external CSS resources.