React basics
Useful links
Recommended React learning path for beginners:
- Not required: (in Polish) Wprowadzenie do React wraz z przykładem projektu
- React vs jQuery - a same application in both tools (for those familiar with jQuery)
- React Official Docs - Quick Start
- Build Your First Production Quality React App + code
- Your first applications in React with Create React App
About MobX here.
About Flux/Redux here.
About Webpack:
- Getting Started with Webpack: Module Bundling Magic
- Setup a React Environment Using webpack and Babel with yarn
JSX syntax
Example
When writing in React, it is recommended to use JSX syntax. Here is an example of JSX code:
return (
<MyButton color="blue" shadowSize={2}>
Click Me
</MyButton>
)
Compiles into:
return React.createElement(
MyButton,
{color: 'blue', shadowSize: 2},
'Click Me'
)
Components names must be capitalized to distinguish it from HTML elements.
Components
Components names must be capitalized.
React elements are immutable. Once you create an element, you can't change its children or attributes.
React functions are "pure" because they do not attempt to change their inputs, and always return the same result for the same inputs. All React components must act like pure functions with respect to their props.
Passing props to component and displaying it
An example of displaying props in a component written in ES6/JSX:
import React from 'react'
export default class Greeter extends React.Component {
render () {
return (
<div>Hello {this.props.name} !</div>
)
}
}
Greeter.propTypes = {
name: React.PropTypes.string
}
Greeter.defultProps = {
name: 'Mateusz'
}
Code of an application that is passing a prop to a component:
import React from 'react'
import Greeter from './greeter'
export default class App extends React.Component {
render () {
return (
<div>
<Greeter name="Bob" />
</div>
)
}
}
name
attribute is a property which will be available in Greeter
component as this.props.name
.
State
The state will be only updated when you use a setState()
method, not by directly write to state property:
// Wrong, doesn't update a component. NEVER DO THAT.
this.state.comment = 'Hello'
// Correct.
this.setState({comment: 'Hello'})
State and state updates can be asynchronous, so don't rely on their values:
// Wrong
this.setState({
counter: this.state.counter + this.props.increment
})
// Correct
this.setState((prevState, props) => ({
counter: prevState.counter + props.increment
}))
defaultProps
and propTypes
Always strive to define them because component should always be independent from external props when rendering:
Counter.propTypes = { initialCount: React.PropTypes.number }
Counter.defaultProps = { initialCount: 0 }
Handling events
Example of handling events:
this.handleClick
and pass it to onClick
, this
will be undefined
when the function is actually called.
class Toggle extends React.Component {
constructor (props) {
super(props)
this.state = {isToggleOn: true}
// This binding is necessary to make `this` work in the callback
this.handleClick = this.handleClick.bind(this)
}
handleClick () {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}))
}
render () {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
)
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
)
Quirks
ES6 Map.forEach()
and JSX
Source - forEach over es6 Map in JSX
Map.forEach()
doesn't return anything so we can't iterate over Map()
object using this method. Instead we have to use Array.map()
but first we have to convert a Map
object to an Array
. We can achieve it using method entries()
:
render (
<div>
{
this.store.todos.forEach(function(todo, key) {
...
})
// doesnt return anything, so instead we have to use:
this.store.todos.entries().map(function(result) {
const key = result[0]
const todo = result[1]
...
})
}
</div>
)
React.createClass
vs React.Component
React.Component
were introduced in React v0.13 which the main feature was ES6 support. React.createClass
will be deprecated in v16.0.