React redux
- 2. REACT
React is a JavaScript Library for building user interfaces.
• Focus on the UI, not a Framework like Angular or Ember
• One-way reactive data flow (no two-way data binding)
• Components
• Virtual DOM
- 5. THE HELLO WORLD
import React from 'react'
import ReactDOM from 'react-dom'
const exampleElement = document.getElementById('example')
ReactDOM.render(<h1>Hello, world!</h1>, exampleElement)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<script src="bundle.js"></script>
</head>
<body>
<div id="example"></div>
</body>
</html>
- 6. JSX
JSX is a JavaScript syntax extension that looks similar to
XML is used to create React Elements
// Input (JSX):
var app = <h2 color="blue" />
// Output (JS):
var app = React.createElement(h2, {color:"blue"})
- 7. STATEFUL COMPONENT
class DeleteLink extends React.Component{
constructor(props){
super()
this.state = {}
this.index = props.index
this.deleteComponentHandler = this.deleteComponentHandler.bind(this)
}
render(){
return(
<a href="#" className="delete-component" onClick={(e) => {
e.preventDefault()
this.deleteComponentHandler(index)
}}>
<i className="fa fa-trash" aria-hidden="true"></i>
</a>
)
}
deleteComponentHandler(index){
// do something
}
}
export default DeleteLink
- 8. COMPONENT LIFECYCLE
class MyComponent extends React.Component {
constructor() {
}
render() { //pure returns the view calling jsx tags
}
getInitialState() { // called before the component is mounted, inits this.state
}
getDefaultProps() { // inits this.props
}
componentWillMount() { called once before the initial render
}
componentDidMount() { // called once after the initial render
}
componentWillReceiveProps() { // called when the props are updated
}
shouldComponentUpdate() { // should update the component in the three?
}
componentWillUpdate() { // do something before an update, not to call
this.setState
}
componentDidUpdate() { // do something when the components have been updated
}
}
- 9. STATELESS COMPONENT
import React, {PropTypes} from 'react'
const DeleteLink = ({index}) => {
return (
<a href="#" className="delete-component">
<i className="fa fa-trash" aria-hidden="true"></i>
</a>
)
}
DeleteLink.propTypes = {
index: PropTypes.number.isRequired,
deleteComponentHandler: PropTypes.func.isRequired
}
export default DeleteLink
- 12. REDUX
▸ Handles the state of the Application with predictable
behaviour
▸ Takes ideas from ELM
▸ Store: The state
▸ Actions: The intent of changing the state
▸ Reducer: (previousState, action) => newState
▸ Components: The view (Here goes react)
▸ Containers: Components decorators
- 14. STORE
import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { createStore } from 'redux'
import todoApp from './reducers'
import App from './components/App'
let store = createStore(todoApp)
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('main')
)
- 15. THE APP
import React from 'react'
import AddTodoContainer from '../containers/AddTodoContainer'
import VisibleTodoList from '../containers/VisibleTodoList'
const App = () => (
<div>
<AddTodoContainer />
<VisibleTodoList />
</div>
)
export default App
- 16. THE ADD TODO
import React, { PropTypes } from 'react'
let AddTodo = ({ onInputSubmit }) => {
let input
return (
<div>
<form onSubmit={(e) => onInputSubmit(e, input)}>
<input ref={node => input = node } />
<button type="submit">
Add Todo
</button>
</form>
</div>
)
}
AddTodo.propTypes = {
onInputSubmit: PropTypes.func.isRequired
}
export default AddTodo
- 17. THE CONTAINER
import React from 'react'
import { connect } from 'react-redux'
import { addTodo } from '../actions'
import AddTodo from '../components/AddTodo'
const mapDispatchToProps = (dispatch) => {
return {
onInputSubmit: (e, input) => {
e.preventDefault()
if (!input.value.trim()) {
return
}
dispatch(addTodo(input.value))
input.value = ''
}
}
}
const AddTodoContainer = connect(null, mapDispatchToProps)(AddTodo)
export default AddTodoContainer
- 19. THE REDUCER
import { combineReducers } from 'redux'
import todos from './todos'
const todoApp = combineReducers({
todos
})
const todos = (state = [], action) => {
switch (action.type) {
case 'ADD_TODO':
return [
…state,
{id: action.id, text: action.text, completed: false}
]
default:
return state
}
}
export default todoApp
- 20. THE TODO LIST
import React, { PropTypes } from 'react'
import Todo from './Todo'
const TodoList = ({ todos }) => (
<ul>
{todos.map(todo =>
<Todo
key={todo.id}
{...todo}
/>
)}
</ul>
)
TodoList.propTypes = {
todos: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.number.isRequired,
completed: PropTypes.bool.isRequired,
text: PropTypes.string.isRequired
}).isRequired).isRequired
}
export default TodoList
- 21. THE TODO ITEM
import React, { PropTypes } from 'react'
const Todo = ({ completed, text }) => (
<li>
{text}
</li>
)
Todo.propTypes = {
completed: PropTypes.bool.isRequired,
text: PropTypes.string.isRequired
}
export default Todo
- 22. THE TODO LIST CONTAINER
import { connect } from 'react-redux'
import TodoList from '../components/TodoList'
const mapStateToProps = (state) => {
return {
todos: state.todos
}
}
const mapDispatchToProps = (dispatch) => {
return { }
}
const VisibleTodoList = connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)
export default VisibleTodoList
- 23. ES6 THE IMMUTABLE
A new array
[
…state,
{id: action.id, text: action.text, completed: true}
]
A new object
return {...image, _destroy: {value: true}}
Immutable.js
https://facebook.github.io/immutable-js/