React: The Good, the Bad, & the Ugly
What is React?
React is a library, not a framework
- Data -> View
- Uses a 'Shadow DOM'
- Reconciliation
import React, { Component } from 'react';
import { render } from 'react-dom';
class App extends Component {
constructor() {
super(...arguments);
this.state = {
thisCan: 'be whatever you want'
};
this.setState({
and: 'can be managed and abstracted',
however: 'you wish'
});
}
render() {
return (
<div>
Hello World
{this.state.thisCan}
</div>
);
}
}
render(<App />, document.getElementById('app'));
The Good
React doesn't care
- Give it a base state
- Mutate VIA provided tools
- Data can be from anywhere
import React, { Component } from 'react';
import { render } from 'react-dom';
class App extends Component {
constructor(...args) {
super(...args);
this.state = {
currentCount: 0
};
setInterval(() => {
this.setState({
currentCount: this.state.currentCount + 1
});
//Every time setState is called,
//React diff's the changed state and fires off a DOM update!
}, 100);
}
render() {
const { currentCount } = this.state;
return (
<div>Count: {currentCount}</div>
);
}
}
render(<App />, document.getElementById('app'));
JSX
- Logic in the view
- render() can handle JSX, HTML, or Javascript
- Can be abstracted
import React, { Component } from 'react';
import { render } from 'react-dom';
class App extends Component {
render() {
return (
<div>
Hello World
<span className='container'>
Goodbye World
</span>
</div>
);
}
}
render(<App />, document.getElementById('app'));
Component Emphasis
- Compartmentalize Everything
- Easy abstraction to keep things organized
- Complexity is up to you
import React, { Component } from 'react';
import { render } from 'react-dom';
class SubComponent extends Component {
render() {
return (
<div>
I am a sub component!
</div>
);
}
}
const subComponent = <SubComponent />;
class App extends Component {
render() {
return (
<div>
You always need a wrapper element!
<SubComponent /> { /* Comments in JSX need to be within braces */ }
{ /* Components need to have the first letter capitalized! */ }
{ /* <subComponent /> will not work! */ }
{subComponent /* This works because we're rendering a variable */}
</div>
);
}
}
render(<App />, document.getElementById('app'));
Speed
- React renders things quickly
- Set the standard for the industry
Active Community
- 957 Contributors
-
26208 packages found for "react" on npm
-
Backed by numerous large companies, notably Facebook
Powerful and Numerous Community-Supported Modules
- React is lightweight, lots to extend on
- Redux, MobX, Cerebral
- React-router
Multi-Platform
- Reconciliation...
- React-DOM
- React-Native
- React-VR
React-Fiber
- Rewrite of the Reconciliation Engine
- 92.2% complete as of now
The Bad
- Who really needs privacy?
- Sketchy License
- Lawyers have disallowed use of React in certain scenarios
Webpack & Getting Started Overhead
Just install...
- Webpack
- Babel
- All necessary presets
- Transformers
- Plugins
const path = require('path');
const BUILD_DIR = path.resolve(__dirname, '../server/static/');
const APP_DIR = path.resolve(__dirname, './app');
const TARGET = process.env.npm_lifecycle_event;
process.env.BABEL_ENV = TARGET;
const config = {
entry: [
APP_DIR + '/index.jsx'
],
output: {
path: BUILD_DIR,
filename: 'bundle.js'
},
module : {
loaders : [
{
test : /\.jsx?/,
include : APP_DIR,
loader : 'babel'
},
{
test: /\.(png|jpg)$/,
include : APP_DIR,
loader: 'url-loader?limit=8192'
},
{
test: /\.js$/,
include: APP_DIR,
loader: 'babel'
},
{
test: /\.json$/,
include: APP_DIR,
loader: 'babel'
}
],
},
resolve: {
extensions: [
'',
'.js',
'.jsx',
'.css',
'.scss'
]
}
};
module.exports = config;
webpack.config.js
State Management
class A extends Component {
constructor(...args) {
super(...args);
this.state = {
a: 'b'
}
}
}
class B extends Component {
constructor(...args) {
super(...args);
this.state = {
b: 'a'
}
}
}
State managed per-component
Requires external libraries to sync across components
class A extends Component {
constructor(...args) {
super(...args);
this.state = {
a: 'b'
}
}
render() {
return <B a={this.state.a} />
}
}
class B extends Component {
constructor(...args) {
super(...args);
this.state = {
b: this.props.a || 'a'
}
}
}
Functional Components
class A extends Component {
constructor(...args) {
super(...args);
this.state = {
a: 'b'
}
}
render() {
return <B a={this.state.a} />
}
}
const B = function(props) {
return (
<div>{props.a || 'a'}</div>
);
}
Modeling Complex Objects
- Heavy emphasis on breaking things down means when you can't, you have trouble
- Rendering recursively ends up okay, but editing gets messy
- No 2-way binding prevents an easy solution
The Ugly
JSX, again
- Tightly couples view with logic
- Discourages more elegant abstractions
- Literally just syntactic sugar
class Hello extends React.Component {
render() {
return (
<div>
Hello {this.props.toWhat}
</div>
);
}
}
class Hello extends React.Component {
render() {
return React.createElement(
'div',
null,
`Hello ${this.props.toWhat}`
);
}
}
Clunky Addons
- Limited base app leads to lots of modules
- Hugely varied codebases mean not all modules will play nice
- Isomorphism, Hot-Loader
Javascript
You're writing Javascript.
Your team is writing Javascript.
React isn't picky about what you do, and....
Most people suck at writing Javascript.
State Management
- Redux?
- MobX? Cerebral?
- DIY?
Shameless Plug, Redux Black Magic:
https://github.com/krishnaglick/redux-black-magic
Overall?
- Powerful
- Reliable
- Worth the trouble
Contact
/krishnaglick on Github
@krishnaglick on Twitter
@prometheus on ODevs Slack
React: The Good, the Bad, & the Ugly
By Krishna Glick