...in 20 minutes
React is a Javascript Library for Building User Interfaces
React is a Javascript Library for Building User Interfaces
React is a Javascript Library for Building User Interfaces
/**
* https://npmcdn.com/react@15.0.1/dist/react.js
* https://npmcdn.com/react-dom@15.0.1/dist/react-dom.js
*/
ReactDOM.render(
React.createElement('h1', null, 'Hello World!'),
document.getElementById('app')
)
Literally: Hello World Codepen
React is all about components.
A component is essentially a description of a piece of user interface.
These are composed together to form an application.
Think... Legos :)
Components all the way down
Components are composed of components are composed of components.
React.createElement(
'button', // 1st arg is type (string for DOM OR custom component)
{className: 'btn btn-md btn-primary', someProp: '2nd arg is props!'},
'3rd argument is the "props.children"'
)
React.createElement('div', null,
React.createElement('div', null,
React.createElement('div', null,
'Components inside of components inside of components'
)
)
)
A component is a pure function of *state.
*state in, UI out.
A component’s behavior is defined by its lifecycle methods.
*state being the combination of both this.state and this.props.
The majority of components can be described, simply, as a pure function of props.
This is the "simplified" API which is the preferred method of defining Components.
No state. No Lifecycle.
/**
* See: http://facebook.github.io/react/docs/reusable-components.html#stateless-functions
*/
const SomeStatelessComponent = (props) => {
return (
<div>
<h1>Hello, I am SomeStatelessComponent!</h1>
<h3>{props.message}</h3>
// Only render children when we are not loading
{props.loading ? 'Loading...' : props.children}
</div>
)
};
Props + State + Lifecycle
/** See http://facebook.github.io/react/docs/component-specs.html */
const SomeStatefulComponent = React.createClass({
// Define the initial "state" of our component
getInitialState() {
// state is updated via this.setState({loading: true})
return {loading: false}
},
render() {
// Here, we have access to this.props as well as this.state
return (
<div>
<h1>Hello, I am SomeStatefulComponent!</h1>
<h3>{this.props.message}</h3>
// Only render children when we are not loading
{this.state.loading ? 'Loading...' : this.props.children}
</div>
)
}
});
+ More...
import React, {PropTypes} from 'react'
const examplePropTypes = {
// Require the title
title: PropTypes.string.isRequired,
// Optional function
doThisWhenClicked: PropTypes.func,
// Some array of "special things with a certain shape"
specialThings: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.number.isRequired,
name: PropTypes.string.isRequired,
deleteMe: PropTypes.func.isRequired,
specialOptionalAttribute: PropTypes.any,
tags: PropTypes.arrayOf(PropTypes.string),
})
).isRequired,
}
const MyComponent = (props) => {/*...*/}
MyComponent.propTypes = examplePropTypes
const MyComponent = React.createClass({
propTypes: examplePropTypes,
// ...
})
class MyComponent extends React.Component {/*...*/}
MyComponent.propTypes = examplePropTypes
An API to declare and validate props.
A component's propTypes are essentially its way of saying “if you are going to use me, this is what I need”.
Helpful console warnings + Great when visiting a component that you did not author (or after 6 months)
Would you like some sugar with your function calls?
Fear not!
It is nothing more than syntactical sugar on top of the Javascript function calls you already know and love.
import React from 'react';
const Header = ({title, subtitle}) => (
<section className="hero">
<h1 className="title">
{title}
</h1>
<h2 className="subtitle">
{subtitle}
</h2>
</section>
);
All 3 examples are equivalent
It may look like
import { createElement as el } from 'react';
const HeaderWithoutJsx = ({title, subtitle}) => (
el('section', {className: 'hero'},
el('h1', {className: 'title'},
title
),
el('h2', {className: 'subtitle'},
subtitle + ' Without JSX'
)
)
);
import { DOM } from 'react';
const {section, div, h1, h2} = DOM;
const HeaderWithDomHelpers = ({title, subtitle}) => (
section({className: 'hero'},
h1({className: 'title'},
title
),
h2({className: 'subtitle'},
subtitle + ' Without JSX (using DOM helpers)'
)
)
);
In React, all data flows from the top to the bottom.
/**
* The parent "owns" and manages the state.
* It passes down props to its children
* Some props are data and the children simply display them "read"
* Some props are functions that can update/affect state "write"
*/
const ShoppingCart = React.createClass({
getInitialState() {
return {
cartQuantity: 0,
};
},
incrementQuantity() {
this.setState({
cartQuantity: this.state.cartQuantity + 1,
});
},
render() {
const { cartQuantity } = this.state;
return (
<div>
<h3>A Great Item</h3>
<QuantityDisplayer quanity={cartQuantity} />
<MoarButton increment={this.incrementQuantity} />
</div>
)
}
});
/**
* The children require/accept props from "the great above" (parent)
*/
const QuantityDisplayer = (props) => (
<div>
Quantity in cart: {props.quantity}
</div>
);
QuantityDisplayer.propTypes = {
quantity: React.PropTypes.number.isRequired,
};
const MoarButton = (props) => (
<button onClick={props.increment}>
MOAR!!!
</button>
);
MoarButton.propTypes = {
increment: React.PropTypes.func.isRequired,
};
A Controlled component does not maintain its own internal state; the component renders purely based on props.
/** A Form w/ a "controlled" component (input) */
const SomeForm = React.createClass({
getInitialState() {
return {firstName: ''}
},
handleChangeFirstName(event) {
this.setState({
firstName: event.target.value
})
},
handleSubmit(event) {
event.preventDefault()
alert(`First Name: ${this.state.firstName}!`)
},
render() {
const {firstName} = this.state
return (
<div>
<h3>A Great Form</h3>
<form onSubmit={this.handleSubmit}>
First Name <input
type="text"
value={firstName}
onChange={this.handleChangeFirstName}
/>
<button>Submit</button>
</form>
</div>
)
}
})
input simply renders the value that is given. The DOM event is handled by handleChangeFirstName and the new value trickles back down.
React 101: The Condensed Version - Erik Aybar