| ES6 | ES5 |
|---|---|
const fn = (n) => n * n |
function fn(n) { return n * n } |
const fn = (n) => { n += 1; return n } |
function fn(n) { n += 1; return n } |
const fn = (name) => ({ value: name }) |
function fn(name) { return { value: name }; } |
const fn = ({x, y}) => x + y |
function fn(object) { var x = object.x, y = object.y; return x + y } |
const newObject = { value: 1, ...object } |
var newObject = Object.assign({ value: 1 }, object) Object.assign |
const newArray = [...array, 1] |
var newArray = array.slice(0, array.length).concat(1) |
const a = 3; const object = { a } |
var a = 3; var object = { a: a } |
index.js contains the loading code
components/*.js are the rendering components (where the HTML is created, kinda)
constants.js contains constants, as well as functions to derive values from those constants
models.js is in charge of knowing how the data is structured
calculations.js this is where we calculate the pole allowable weight (not sure if it's weight, but it's some value that we
calculate according to formulas provided by the client)
cordova.js basic functions to get a signature, an image or a date (COTG)
actions.js these are all the actions that can be performed in the application
reducers.js these are the redux reducers
Redux holds the state of the application in what is called a store.
React is in charge of rendering the components/*.js everytime the state in store changes. The store is initialized in index.js.
store has a dispatch method, that is used to trigger actions, described below.
Actions can be of 2 kinds: either return an object, that will be passed to the reducers (kind 1); or a function that will receive the state, and be able to dispatch other actions (kind 2). Example:
// Kind 1
const addImage = (source) => ({
type: 'ADD_IMAGE',
source: source
})
// Kind 2 -- used when some validation is needed, or when some async action needs to be done
const safeAddImage = (source) => {
return (dispatch, getState) => {
if (source == null) {
alert('Source is null!')
return
}
if (getState().canAddImage === false) {
alert('Cant add image!')
return
}
// Everything looks good
dispatch({ type: 'ADD_IMAGE', source: source })
// equivalent to:
// dispatch(addImage(source))
}
}These receive actions of kind 1, as well as the previous state. Their job is to return the new state. Example:
function imagesReducer(state = [], action) {
switch(action.type) {
case 'ADD_IMAGE': {
return [...state, action.source]
// equivalent to:
// var newState = state.slice(0, state.length)
// newState.concat(action.source)
// return newState
}
default: {
return state
}
}Reducers are combined in a single reducer, that will be our state representation. Example:
const rootReducer = combineReducers({ images: imagesReducer })Our state would be:
const store = createStore(rootReducer)
// state equals { images: [] }
store.dispatch(addImage('http://img.com/myimg'))
// state equals { images: ['http://img.com/myimg'] }These are either a class with a render method, or a single function (which is a render method).
To insert the state into them, we can either set it in the properties (<div thisIsAProperty="value"/>) or tell redux to pass it in the props with a mapStateToProps method.
Example:
/* components/App.js */
import Images from './Images';
function mapStateToProps(state) {
return { images: state.images }
}
function App(props) {
const images = props.images
return (
<Images sources={images} />
)
}
export connect(mapStateToProps)(App)/* components/Images.js */
export function Images(props) {
const sources = props.sources
return (
<div className="images">
{ sources.map(source =>
<img src={source} />
) }
</div>
)
}/* index.js */
import React from 'react';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import App from './components/App';
import rootReducer from './reducers';
const store = createStore(rootReducer)
React.render(
<Provider store={store}>
<App />
</Provider>,
document.querySelector('#root')
)