- Place each component in a separate folder
- Avoid having shared resources between components (css, images etc.)
- Keep all components' folders in the same parent folder (avoid nesting)
/src/components/Navigation/icon.svg
/src/components/Navigation/Navigation.js
/src/components/Navigation/Navigation.less
/src/components/Navigation/Navigation.test.js
/src/components/Navigation/Navigation.ru-RU.less
/src/components/Navigation/package.json
For more information google for component-based UI development.
Use BEM approach for naming CSS classes. See also SUIT CSS for inspiration.
// CSS
.ComponentName { }
.ComponentName--modifier { }
.ComponentName-elementName { }
.ComponentName-elementName--modifier { }
// JSX
<nav className="Navigation">
<ul className="Navigation-items">
<li className="Navigation-item Navigation-item--selected">
<a className="Navigation-link" href="/products">Products</a>
</li>
<li className="Navigation-item">
<a className="Navigation-link" href="/services">Services</a>
</li>
</ul>
</nav>
// LESS
.Navigation {
&-items {
margin: 0;
padding: 0;
list-style-type: none;
text-align: center;
}
&-item {
display: inline-block;
vertical-align: top;
}
&-link {
display: block;
padding: 0 25px;
outline: 0;
border: 0;
color: @default-color;
text-decoration: none;
line-height: 25px;
transition: background-color .3s ease;
&,
.Navigation-items:hover & {
background: @default-bg-color;
}
&--selected,
.Navigation-items:hover &:hover {
background: @active-bg-color;
}
}
}
- Use Babel transpiler for your source code
- Use ES6 classes for creating new React components
- Use higher-order components to extend the functionality of existing components
import './SampleComponent.less';
import React, { Component } from 'react';
class SampleComponent extends Component {
static propTypes = { ... };
static defaultProps = { ... };
constructor() {
super();
this.state = { ... };
}
componentDidMount() {
// ...
}
componentWillUnmount() {
// ...
}
shouldComponentUpdate() {
// ...
}
render() {
return (
<div className="SampleComponent">
</div>
);
}
}
export default SampleComponent;
Put custom methods and properties at the bottom of the file, after the render() method.
// setViewport.js
import React, { Component } from 'react';
import { canUseDOM } from 'react/lib/ExecutionEnvironment';
function setViewport(ComposedComponent) {
return class Viewport extends Component {
constructor() {
super();
this.state = {
viewport: canUseDOM ?
{width: window.innerWidth, height: window.innerHeight} :
{width: 1366, height: 768} // Default size for server-side rendering
};
this.handleResize = () => {
let viewport = {width: window.innerWidth, height: window.innerHeight};
if (this.state.viewport.width !== viewport.width ||
this.state.viewport.height !== viewport.height) {
this.setState({viewport: viewport});
}
};
}
componentDidMount() {
window.addEventListener('resize', this.handleResize);
window.addEventListener('orientationchange', this.handleResize);
}
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize);
window.removeEventListener('orientationchange', this.handleResize);
}
render() {
return <ComposedComponent {...this.props} viewport={this.state.viewport}/>;
}
};
};
export default setViewport;
// MyComponent.js
import React from 'react';
import setViewport from './setViewport';
@setViewport
class MyComponent {
render() {
let { width, height } = this.props.viewport;
return <div>{'Viewport: ' + width + 'x' + height}</div>;
}
}
export default MyComponent;