store.dispatch(decrease())}
12 | // onSum = {(a,b)=> store.dispatch(getSum(a, b))}
13 | // onRandomImages = {() => store.dispatch(getRandomImages)}
14 | // />,
15 | // document.getElementById('root')
16 | // )
17 | // }
18 | // render();
19 |
20 | // store.subscribe(render);
21 |
22 | render(
23 |
24 |
25 | ,
26 | document.getElementById('root')
27 | )
28 |
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v05. react-redux -- Provider (shorter)/redux/actions/index.js:
--------------------------------------------------------------------------------
1 | import $ from 'jquery'
2 | export const decrease = () => ({ type: 'DECREMENT' });
3 |
4 | export const getSum = (a, b) => ({ type: 'SUM', a, b });
5 |
6 | export const getRandomImages = (dispatch, state) => {
7 | dispatch({ type: 'IMAGES_LOADING' });
8 | var imgurAPI = "https://api.imgur.com/3/gallery/random/random/1";
9 | $.getJSON(imgurAPI).done(data =>
10 | dispatch({ type: 'IMAGES', data:data.data}))
11 | }
12 |
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v05. react-redux -- Provider (shorter)/redux/middlewares/index.js:
--------------------------------------------------------------------------------
1 | // middleware
2 | export const logger = store => next => action => {
3 | console.group('logger')
4 | console.log('currentState == ', store.getState());
5 | console.info('next(action) // action == ', action)
6 | next(action);
7 | console.log('nextState == ', store.getState());
8 | console.groupEnd('logger')
9 | }
10 |
11 | //second middleware
12 | export const crashReporter = store => next => action => {
13 | try{
14 | next(action);
15 | }catch(err){
16 | console.group('crashReporter');
17 | console.error('error happen with action == ', action);
18 | console.error(err);
19 | console.groupEnd('crashReporter');
20 | }
21 |
22 | }
23 | //third middleware
24 | export const thunk = store => next => action => {
25 | if(typeof action === 'function'){
26 | action(store.dispatch, store.getState());
27 | }else{
28 | next(action);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v05. react-redux -- Provider (shorter)/redux/reducers/counter.js:
--------------------------------------------------------------------------------
1 | export default function counter(state = {result:0, loading:false}, action){
2 | switch (action.type) {
3 | case 'DECREMENT':
4 | return {...state,
5 | result: state.result - 1};
6 | default:
7 | return state;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v05. react-redux -- Provider (shorter)/redux/reducers/images.js:
--------------------------------------------------------------------------------
1 | export default function images(state = {data:[],
2 | loading:"Please click the 'Random Images' button"}, action){
3 | switch (action.type) {
4 | case 'IMAGES':
5 | return {...state,
6 | data: action.data,
7 | loading: "loaded"
8 | };
9 | case 'IMAGES_LOADING':
10 | return {...state,
11 | loading: "loading..."
12 | };
13 | default:
14 | return state;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v05. react-redux -- Provider (shorter)/redux/reducers/index.js:
--------------------------------------------------------------------------------
1 | import counter from './counter'
2 | import images from './images'
3 | import sum from './sum'
4 |
5 | export default function combineReducer(currentState, action) {
6 | var nextState = {...currentState};
7 | return {
8 | count:counter(nextState.count, action),
9 | sum: sum(nextState.sum, action),
10 | images: images(nextState.images, action)
11 | };
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v05. react-redux -- Provider (shorter)/redux/reducers/sum.js:
--------------------------------------------------------------------------------
1 | export default function sum(state = 3, action){
2 | switch (action.type) {
3 | case 'SUM':
4 | return parseInt(action.a) + parseInt(action.b);
5 | default:
6 | return state;
7 | }
8 | }
9 |
10 | function funcWithError(){
11 | throw Error('an error from sum')
12 | }
13 |
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v05. react-redux -- Provider (shorter)/redux/store/config.js:
--------------------------------------------------------------------------------
1 | import { createStore, applyMiddleware, compose} from 'redux'
2 | import combineReducer from '../reducers/index'
3 | import {logger, crashReporter, thunk} from '../middlewares/index'
4 |
5 |
6 | const store = createStore(combineReducer, {}, compose(
7 | applyMiddleware(logger, crashReporter, thunk),
8 | window.devToolsExtension ? window.devToolsExtension() : f => f
9 | ));
10 |
11 | export default store;
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v05. react-redux -- Provider (shorter)/server.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack')
2 | var webpackDevMiddleware = require('webpack-dev-middleware')
3 | var webpackHotMiddleware = require('webpack-hot-middleware')
4 | var config = require('./webpack.config')
5 |
6 | var app = new (require('express'))()
7 | var port = 3000
8 |
9 | var compiler = webpack(config)
10 | app.use(webpackDevMiddleware(compiler, { noInfo: true, publicPath: config.output.publicPath }))
11 | app.use(webpackHotMiddleware(compiler))
12 |
13 | app.get("/", function(req, res) {
14 | res.sendFile(__dirname + '/index.html')
15 | })
16 |
17 | app.listen(port, function(error) {
18 | if (error) {
19 | console.error(error)
20 | } else {
21 | console.info("==> 🌎 Listening on port %s. Open up http://localhost:%s/ in your browser.", port, port)
22 | }
23 | })
24 |
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v05. react-redux -- Provider (shorter)/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var webpack = require('webpack')
3 |
4 | module.exports = {
5 | devtool: 'cheap-module-eval-source-map',
6 | entry: [
7 | 'webpack-hot-middleware/client',
8 | './index'
9 | ],
10 | output: {
11 | path: path.join(__dirname, 'dist'),
12 | filename: 'bundle.js',
13 | publicPath: '/static/'
14 | },
15 | plugins: [
16 | new webpack.optimize.OccurenceOrderPlugin(),
17 | new webpack.HotModuleReplacementPlugin()
18 | ],
19 | module: {
20 | loaders: [
21 | {
22 | test: /\.js$/,
23 | loaders: [ 'babel' ],
24 | exclude: /node_modules/,
25 | include: __dirname
26 | }
27 | ]
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v06. react-redux -- Container, combineReducers, middlewares (thunk, logger)/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "react"],
3 | "plugins": ["transform-object-rest-spread"],
4 | "env": {
5 | "development": {
6 | "presets": ["react-hmre"]
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v06. react-redux -- Container, combineReducers, middlewares (thunk, logger)/components/Counter.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | export default class Counter extends Component{
3 | constructor(props) {
4 | super(props)
5 | }
6 | render() {
7 | const {count:{result},onDecrement} = this.props;
8 | return (
9 |
10 | Clicked:
{result} times
11 |
12 |
13 |
14 | )
15 | }
16 | }
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v06. react-redux -- Container, combineReducers, middlewares (thunk, logger)/components/Examples.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import Counter from '../containers/Counter'
3 | import Sum from '../containers/Sum'
4 | import RandomImages from '../containers/RandomImages'
5 |
6 | export default class Examples extends Component {
7 | constructor(props) {
8 | super(props)
9 | }
10 | render() {
11 | return (
12 |
13 |
React
14 |
15 |
16 |
17 |
18 | )
19 | }
20 | }
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v06. react-redux -- Container, combineReducers, middlewares (thunk, logger)/components/RandomImages.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 |
3 | export default class RandomImages extends Component{
4 | constructor(props) {
5 | super(props)
6 | }
7 | render() {
8 | const {images:{loading, data},onRandomImages} = this.props;
9 | return (
10 |
11 |
13 |
CountStatus:
14 |
15 | {loading}
16 |
17 |
18 |
19 | )
20 | }
21 | }
22 | function ImageList(props) {
23 | return (
24 |
25 | {props.images.map((image)=>
26 |

)}
29 |
30 | )
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v06. react-redux -- Container, combineReducers, middlewares (thunk, logger)/components/Sum.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | export default class Sum extends Component{
3 | constructor(props) {
4 | super(props)
5 | this.state = {a:1, b: 2}
6 | }
7 | render() {
8 | const {state:{a,b}, props:{sum, onSum}} = this;
9 | return (
10 |
11 |
this.setState({a: e.target.value})}/>
13 | +
this.setState({b: e.target.value})}/>
15 | =
{sum}
16 |
17 |
18 |
19 | )
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v06. react-redux -- Container, combineReducers, middlewares (thunk, logger)/containers/Counter.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { connect } from 'react-redux'
3 | import { decrease } from '../redux/actions/index'
4 | import Counter from '../components/Counter'
5 |
6 | export default connect(
7 | (state, ownProps) => ({
8 | count: state.count,
9 | prop2: state.prop // just an example in case of many properties
10 | }),
11 | {
12 | onDecrement: decrease,
13 | func2: () => {} // just an example in case you need many functions from dispatch
14 | }
15 | )(Counter)
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v06. react-redux -- Container, combineReducers, middlewares (thunk, logger)/containers/RandomImages.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import RandomImages from '../components/RandomImages'
3 | import { connect } from 'react-redux'
4 | import { getRandomImages } from '../redux/actions/index'
5 |
6 | export default connect(
7 | (state, ownProps) =>( {
8 | images: state.images
9 | }),
10 | {onRandomImages: () => getRandomImages}
11 | )(RandomImages)
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v06. react-redux -- Container, combineReducers, middlewares (thunk, logger)/containers/Sum.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { getSum } from '../redux/actions/index'
3 | import React, { Component } from 'react'
4 | import Sum from '../components/Sum'
5 |
6 |
7 | export default connect(
8 | (state, ownProps) => ( {
9 | sum: state.sum
10 | }),
11 | {onSum: (a,b) => getSum(a, b)}
12 | )(Sum)
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v06. react-redux -- Container, combineReducers, middlewares (thunk, logger)/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | React example
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v06. react-redux -- Container, combineReducers, middlewares (thunk, logger)/index.js:
--------------------------------------------------------------------------------
1 | import {render} from 'react-dom'
2 | import Examples from './components/Examples'
3 | import store from './redux/store/config'
4 | import React from 'react'
5 | import { Provider } from 'react-redux'
6 |
7 | render(
8 |
9 |
10 | ,
11 | document.getElementById('root')
12 | )
13 |
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v06. react-redux -- Container, combineReducers, middlewares (thunk, logger)/redux/actions/index.js:
--------------------------------------------------------------------------------
1 | import $ from 'jquery'
2 | export const decrease = () => ({ type: 'DECREMENT' });
3 |
4 | export const getSum = (a, b) => ({ type: 'SUM', a, b });
5 |
6 | export const getRandomImages = (dispatch, state) => {
7 | dispatch({ type: 'IMAGES_LOADING' });
8 | var imgurAPI = "https://api.imgur.com/3/gallery/random/random/1";
9 | $.getJSON(imgurAPI).done(data =>
10 | dispatch({ type: 'IMAGES', data:data.data}))
11 | }
12 |
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v06. react-redux -- Container, combineReducers, middlewares (thunk, logger)/redux/middlewares/index.js:
--------------------------------------------------------------------------------
1 | export const crashReporter = store => next => action => {
2 | try{
3 | next(action);
4 | }catch(err){
5 | console.group('crashReporter');
6 | console.error('error happen with action == ', action);
7 | console.error(err);
8 | console.groupEnd('crashReporter');
9 | }
10 |
11 | }
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v06. react-redux -- Container, combineReducers, middlewares (thunk, logger)/redux/reducers/counter.js:
--------------------------------------------------------------------------------
1 | export default function counter(state = {result:0, loading:false}, action){
2 | switch (action.type) {
3 | case 'DECREMENT':
4 | return {...state,
5 | result: state.result - 1};
6 | default:
7 | return state;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v06. react-redux -- Container, combineReducers, middlewares (thunk, logger)/redux/reducers/images.js:
--------------------------------------------------------------------------------
1 | export default function images(state = {data:[],
2 | loading:"Please click the 'Random Images' button"}, action){
3 | switch (action.type) {
4 | case 'IMAGES':
5 | return {...state,
6 | data: action.data,
7 | loading: "loaded"
8 | };
9 | case 'IMAGES_LOADING':
10 | return {...state,
11 | loading: "loading..."
12 | };
13 | default:
14 | return state;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v06. react-redux -- Container, combineReducers, middlewares (thunk, logger)/redux/reducers/index.js:
--------------------------------------------------------------------------------
1 | import counter from './counter'
2 | import images from './images'
3 | import sum from './sum'
4 | import { combineReducers } from 'redux'
5 |
6 | export default combineReducers({
7 | count:counter,
8 | sum,
9 | images
10 | })
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v06. react-redux -- Container, combineReducers, middlewares (thunk, logger)/redux/reducers/sum.js:
--------------------------------------------------------------------------------
1 | export default function sum(state = 3, action){
2 | switch (action.type) {
3 | case 'SUM':
4 | return parseInt(action.a) + parseInt(action.b);
5 | default:
6 | return state;
7 | }
8 | }
9 |
10 | function funcWithError(){
11 | throw Error('an error from sum')
12 | }
13 |
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v06. react-redux -- Container, combineReducers, middlewares (thunk, logger)/redux/store/config.js:
--------------------------------------------------------------------------------
1 | import { createStore, applyMiddleware, compose} from 'redux'
2 | import combineReducer from '../reducers/index'
3 | import {crashReporter} from '../middlewares/index'
4 | import createLogger from 'redux-logger'
5 | import thunk from 'redux-thunk'
6 |
7 | const store = createStore(combineReducer, {}, compose(
8 | applyMiddleware(createLogger(), crashReporter, thunk),
9 | window.devToolsExtension ? window.devToolsExtension() : f => f
10 | ));
11 |
12 | export default store;
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v06. react-redux -- Container, combineReducers, middlewares (thunk, logger)/server.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack')
2 | var webpackDevMiddleware = require('webpack-dev-middleware')
3 | var webpackHotMiddleware = require('webpack-hot-middleware')
4 | var config = require('./webpack.config')
5 |
6 | var app = new (require('express'))()
7 | var port = 3000
8 |
9 | var compiler = webpack(config)
10 | app.use(webpackDevMiddleware(compiler, { noInfo: true, publicPath: config.output.publicPath }))
11 | app.use(webpackHotMiddleware(compiler))
12 |
13 | app.get("/", function(req, res) {
14 | res.sendFile(__dirname + '/index.html')
15 | })
16 |
17 | app.listen(port, function(error) {
18 | if (error) {
19 | console.error(error)
20 | } else {
21 | console.info("==> 🌎 Listening on port %s. Open up http://localhost:%s/ in your browser.", port, port)
22 | }
23 | })
24 |
--------------------------------------------------------------------------------
/4. Redux & React/2. React & Redux/v06. react-redux -- Container, combineReducers, middlewares (thunk, logger)/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var webpack = require('webpack')
3 |
4 | module.exports = {
5 | devtool: 'cheap-module-eval-source-map',
6 | entry: [
7 | 'webpack-hot-middleware/client',
8 | './index'
9 | ],
10 | output: {
11 | path: path.join(__dirname, 'dist'),
12 | filename: 'bundle.js',
13 | publicPath: '/static/'
14 | },
15 | plugins: [
16 | new webpack.optimize.OccurenceOrderPlugin(),
17 | new webpack.HotModuleReplacementPlugin()
18 | ],
19 | module: {
20 | loaders: [
21 | {
22 | test: /\.js$/,
23 | loaders: [ 'babel' ],
24 | exclude: /node_modules/,
25 | include: __dirname
26 | }
27 | ]
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/4. Redux & React/3. React-router/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "react"],
3 | "plugins": ["transform-object-rest-spread"],
4 | "env": {
5 | "development": {
6 | "presets": ["react-hmre"]
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/4. Redux & React/3. React-router/components/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Link, browserHistory } from 'react-router'
3 |
4 | export default function App({ children }) {
5 | return (
6 |
7 |
8 | Links:
9 | {' '}
10 | Home
11 | {' '}
12 | Examples02
13 | {' '}
14 | Examples02 with parameter
15 |
16 |
17 |
18 |
19 |
{children}
20 |
21 | )
22 | }
--------------------------------------------------------------------------------
/4. Redux & React/3. React-router/components/Counter.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | export default class Counter extends Component{
3 | constructor(props) {
4 | super(props)
5 | }
6 | render() {
7 | const {count:{result},onDecrement} = this.props;
8 | return (
9 |
10 | Clicked:
{result} times
11 |
12 |
13 |
14 | )
15 | }
16 | }
--------------------------------------------------------------------------------
/4. Redux & React/3. React-router/components/Examples.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import Counter from '../containers/Counter'
3 | import Sum from '../containers/Sum'
4 | import RandomImages from '../containers/RandomImages'
5 |
6 | export default class Examples extends Component {
7 | constructor(props) {
8 | super(props)
9 | }
10 | render() {
11 | return (
12 |
13 |
React
14 |
15 |
16 |
17 |
18 | )
19 | }
20 | }
--------------------------------------------------------------------------------
/4. Redux & React/3. React-router/components/Examples02.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 |
3 | export default class Examples02 extends Component {
4 | constructor(props) {
5 | super(props)
6 | }
7 | render() {
8 | console.log(this.props);
9 | return (
10 |
11 |
Examples 02
12 | Hello, {this.props.params.name || 'world'}
13 |
14 | )
15 | }
16 | }
--------------------------------------------------------------------------------
/4. Redux & React/3. React-router/components/RandomImages.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 |
3 | export default class RandomImages extends Component{
4 | constructor(props) {
5 | super(props)
6 | }
7 | render() {
8 | const {images:{loading, data},onRandomImages} = this.props;
9 | return (
10 |
11 |
13 |
CountStatus:
14 |
15 | {loading}
16 |
17 |
18 |
19 | )
20 | }
21 | }
22 | function ImageList(props) {
23 | return (
24 |
25 | {props.images.map((image)=>
26 |

)}
29 |
30 | )
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/4. Redux & React/3. React-router/components/Sum.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | export default class Sum extends Component{
3 | constructor(props) {
4 | super(props)
5 | this.state = {a:1, b: 2}
6 | }
7 | render() {
8 | const {state:{a,b}, props:{sum, onSum}} = this;
9 | return (
10 |
11 |
this.setState({a: e.target.value})}/>
13 | +
this.setState({b: e.target.value})}/>
15 | =
{sum}
16 |
17 |
18 |
19 | )
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/4. Redux & React/3. React-router/containers/Counter.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { connect } from 'react-redux'
3 | import { decrease } from '../redux/actions/index'
4 | import Counter from '../components/Counter'
5 |
6 | export default connect(
7 | (state, ownProps) => ({
8 | count: state.count,
9 | prop2: state.prop // just an example in case of many properties
10 | }),
11 | {
12 | onDecrement: decrease,
13 | func2: () => {} // just an example in case you need many functions from dispatch
14 | }
15 | )(Counter)
--------------------------------------------------------------------------------
/4. Redux & React/3. React-router/containers/RandomImages.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import RandomImages from '../components/RandomImages'
3 | import { connect } from 'react-redux'
4 | import { getRandomImages } from '../redux/actions/index'
5 |
6 | export default connect(
7 | (state, ownProps) =>( {
8 | images: state.images
9 | }),
10 | {onRandomImages: () => getRandomImages}
11 | )(RandomImages)
--------------------------------------------------------------------------------
/4. Redux & React/3. React-router/containers/Sum.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { getSum } from '../redux/actions/index'
3 | import React, { Component } from 'react'
4 | import Sum from '../components/Sum'
5 |
6 |
7 | export default connect(
8 | (state, ownProps) => ( {
9 | sum: state.sum
10 | }),
11 | {onSum: (a,b) => getSum(a, b)}
12 | )(Sum)
--------------------------------------------------------------------------------
/4. Redux & React/3. React-router/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | React example
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/4. Redux & React/3. React-router/index.js:
--------------------------------------------------------------------------------
1 | import {render} from 'react-dom'
2 | import App from './components/App'
3 | import Examples from './components/Examples'
4 | import Examples02 from './components/Examples02'
5 | import store from './redux/store/config'
6 | import React from 'react'
7 | import { Provider } from 'react-redux'
8 | import { Router, Route, IndexRoute, browserHistory } from 'react-router'
9 | import { syncHistoryWithStore } from 'react-router-redux'
10 | // render(
11 | //
12 | //
13 | // ,
14 | // document.getElementById('root')
15 | // )
16 |
17 | // Create an enhanced history that syncs navigation events with the store
18 | const history = syncHistoryWithStore(browserHistory, store)
19 |
20 | render(
21 |
22 | { /* Tell the Router to use our enhanced history */ }
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | ,
31 | document.getElementById('root')
32 | )
--------------------------------------------------------------------------------
/4. Redux & React/3. React-router/redux/actions/index.js:
--------------------------------------------------------------------------------
1 | import $ from 'jquery'
2 | export const decrease = () => ({ type: 'DECREMENT' });
3 |
4 | export const getSum = (a, b) => ({ type: 'SUM', a, b });
5 |
6 | export const getRandomImages = (dispatch, state) => {
7 | dispatch({ type: 'IMAGES_LOADING' });
8 | var imgurAPI = "https://api.imgur.com/3/gallery/random/random/1";
9 | $.getJSON(imgurAPI).done(data =>
10 | dispatch({ type: 'IMAGES', data:data.data}))
11 | }
12 |
--------------------------------------------------------------------------------
/4. Redux & React/3. React-router/redux/middlewares/index.js:
--------------------------------------------------------------------------------
1 | export const crashReporter = store => next => action => {
2 | try{
3 | next(action);
4 | }catch(err){
5 | console.group('crashReporter');
6 | console.error('error happen with action == ', action);
7 | console.error(err);
8 | console.groupEnd('crashReporter');
9 | }
10 |
11 | }
--------------------------------------------------------------------------------
/4. Redux & React/3. React-router/redux/reducers/counter.js:
--------------------------------------------------------------------------------
1 | export default function counter(state = {result:0, loading:false}, action){
2 | switch (action.type) {
3 | case 'DECREMENT':
4 | return {...state,
5 | result: state.result - 1};
6 | default:
7 | return state;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/4. Redux & React/3. React-router/redux/reducers/images.js:
--------------------------------------------------------------------------------
1 | export default function images(state = {data:[],
2 | loading:"Please click the 'Random Images' button"}, action){
3 | switch (action.type) {
4 | case 'IMAGES':
5 | return {...state,
6 | data: action.data,
7 | loading: "loaded"
8 | };
9 | case 'IMAGES_LOADING':
10 | return {...state,
11 | loading: "loading..."
12 | };
13 | default:
14 | return state;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/4. Redux & React/3. React-router/redux/reducers/index.js:
--------------------------------------------------------------------------------
1 | import counter from './counter'
2 | import images from './images'
3 | import sum from './sum'
4 | import { combineReducers } from 'redux'
5 | import {routerReducer } from 'react-router-redux'
6 |
7 | export default combineReducers({
8 | count:counter,
9 | sum,
10 | images,
11 | routing: routerReducer
12 | })
--------------------------------------------------------------------------------
/4. Redux & React/3. React-router/redux/reducers/sum.js:
--------------------------------------------------------------------------------
1 | export default function sum(state = 3, action){
2 | switch (action.type) {
3 | case 'SUM':
4 | return parseInt(action.a) + parseInt(action.b);
5 | default:
6 | return state;
7 | }
8 | }
9 |
10 | function funcWithError(){
11 | throw Error('an error from sum')
12 | }
13 |
--------------------------------------------------------------------------------
/4. Redux & React/3. React-router/redux/store/config.js:
--------------------------------------------------------------------------------
1 | import { createStore, applyMiddleware, compose} from 'redux'
2 | import combineReducer from '../reducers/index'
3 | import {crashReporter} from '../middlewares/index'
4 | import createLogger from 'redux-logger'
5 | import thunk from 'redux-thunk'
6 |
7 | const store = createStore(combineReducer, {}, compose(
8 | applyMiddleware(createLogger(), crashReporter, thunk),
9 | window.devToolsExtension ? window.devToolsExtension() : f => f
10 | ));
11 |
12 | export default store;
--------------------------------------------------------------------------------
/4. Redux & React/3. React-router/server.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack')
2 | var webpackDevMiddleware = require('webpack-dev-middleware')
3 | var webpackHotMiddleware = require('webpack-hot-middleware')
4 | var config = require('./webpack.config')
5 |
6 | var app = new (require('express'))()
7 | var port = 3000
8 |
9 | var compiler = webpack(config)
10 | app.use(webpackDevMiddleware(compiler, { noInfo: true, publicPath: config.output.publicPath }))
11 | app.use(webpackHotMiddleware(compiler))
12 |
13 | app.use(function(req, res) {
14 | res.sendFile(__dirname + '/index.html')
15 | })
16 |
17 | app.listen(port, function(error) {
18 | if (error) {
19 | console.error(error)
20 | } else {
21 | console.info("==> 🌎 Listening on port %s. Open up http://localhost:%s/ in your browser.", port, port)
22 | }
23 | })
24 |
--------------------------------------------------------------------------------
/4. Redux & React/3. React-router/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var webpack = require('webpack')
3 |
4 | module.exports = {
5 | devtool: 'cheap-module-eval-source-map',
6 | entry: [
7 | 'webpack-hot-middleware/client',
8 | './index'
9 | ],
10 | output: {
11 | path: path.join(__dirname, 'dist'),
12 | filename: 'bundle.js',
13 | publicPath: '/static/'
14 | },
15 | plugins: [
16 | new webpack.optimize.OccurenceOrderPlugin(),
17 | new webpack.HotModuleReplacementPlugin()
18 | ],
19 | module: {
20 | loaders: [
21 | {
22 | test: /\.js$/,
23 | loaders: [ 'babel' ],
24 | exclude: /node_modules/,
25 | include: __dirname
26 | }
27 | ]
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/5. more examples/1. refactor/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "react"],
3 | "plugins": ["transform-object-rest-spread"],
4 | "env": {
5 | "development": {
6 | "presets": ["react-hmre"]
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/5. more examples/1. refactor/components/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Link, browserHistory } from 'react-router'
3 |
4 | export default function App({ children }) {
5 | return (
6 |
7 |
8 | Links:
9 | {' '}
10 | Home
11 | {' '}
12 | Examples02
13 | {' '}
14 | Examples02 with parameter
15 |
16 |
17 |
18 | {' '}
19 |
20 | {' '}
21 |
22 |
23 |
24 |
{children}
25 |
26 | )
27 | }
--------------------------------------------------------------------------------
/5. more examples/1. refactor/components/Examples.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import Counter from '../containers/examples01/Counter'
3 | import Sum from '../containers/examples01/Sum'
4 | import RandomImages from '../containers/examples01/RandomImages'
5 |
6 | export default class Examples extends Component {
7 | constructor(props) {
8 | super(props)
9 | }
10 | render() {
11 | return (
12 |
13 |
React
14 |
15 |
16 |
17 |
18 | )
19 | }
20 | }
--------------------------------------------------------------------------------
/5. more examples/1. refactor/components/Examples02.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 |
3 | export default class Examples02 extends Component {
4 | constructor(props) {
5 | super(props)
6 | }
7 | render() {
8 | console.log(this.props);
9 | return (
10 |
11 |
Examples 02
12 | Hello, {this.props.params.name || 'world'}
13 |
14 | )
15 | }
16 | }
--------------------------------------------------------------------------------
/5. more examples/1. refactor/components/Todos.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 |
3 | export default class Todos extends Component {
4 | render() {
5 | return (
6 |
7 |
Todo List
8 |
9 | )
10 | }
11 | }
--------------------------------------------------------------------------------
/5. more examples/1. refactor/components/Youtube.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 |
3 | export default class Youtube extends Component {
4 | render() {
5 | return (
6 |
7 |
Youtube
8 |
9 | )
10 | }
11 | }
--------------------------------------------------------------------------------
/5. more examples/1. refactor/containers/examples01/Counter.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { connect } from 'react-redux'
3 | import { decrease } from '../../redux/actions/index'
4 | class Counter extends Component{
5 | constructor(props) {
6 | super(props)
7 | }
8 | render() {
9 | const {count:{result},onDecrement} = this.props;
10 | return (
11 |
12 | Clicked:
{result} times
13 |
14 |
15 |
16 | )
17 | }
18 | }
19 |
20 | export default connect(
21 | (state, ownProps) => ({
22 | count: state.examples.count,
23 | prop2: state.prop // just an example in case of many properties
24 | }),
25 | {
26 | onDecrement: decrease,
27 | func2: () => {} // just an example in case you need many functions from dispatch
28 | }
29 | )(Counter)
--------------------------------------------------------------------------------
/5. more examples/1. refactor/containers/examples01/RandomImages.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { connect } from 'react-redux'
3 | import { getRandomImages } from '../../redux/actions/index'
4 |
5 | class RandomImages extends Component{
6 | constructor(props) {
7 | super(props)
8 | }
9 | render() {
10 | const {images:{loading, data},onRandomImages} = this.props;
11 | return (
12 |
13 |
15 |
CountStatus:
16 |
17 | {loading}
18 |
19 |
20 |
21 | )
22 | }
23 | }
24 | function ImageList(props) {
25 | return (
26 |
27 | {props.images.map((image)=>
28 |

)}
31 |
32 | )
33 | }
34 |
35 | export default connect(
36 | (state, ownProps) =>( {
37 | images: state.examples.images
38 | }),
39 | {onRandomImages: () => getRandomImages}
40 | )(RandomImages)
--------------------------------------------------------------------------------
/5. more examples/1. refactor/containers/examples01/Sum.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { getSum } from '../../redux/actions/index'
3 | import React, { Component } from 'react'
4 |
5 | class Sum extends Component{
6 | constructor(props) {
7 | super(props)
8 | this.state = {a:1, b: 2}
9 | }
10 | render() {
11 | const {state:{a,b}, props:{sum, onSum}} = this;
12 | return (
13 |
14 |
this.setState({a: e.target.value})}/>
16 | +
this.setState({b: e.target.value})}/>
18 | =
{sum}
19 |
20 |
21 |
22 | )
23 | }
24 | }
25 |
26 | export default connect(
27 | (state, ownProps) => ( {
28 | sum: state.examples.sum
29 | }),
30 | {onSum: getSum}
31 | )(Sum)
--------------------------------------------------------------------------------
/5. more examples/1. refactor/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | React example
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/5. more examples/1. refactor/redux/actions/index.js:
--------------------------------------------------------------------------------
1 | import $ from 'jquery'
2 | export const decrease = () => ({ type: 'DECREMENT' });
3 |
4 | export const getSum = (a, b) => ({ type: 'SUM', a, b });
5 |
6 | export const getRandomImages = (dispatch, state) => {
7 | dispatch({ type: 'IMAGES_LOADING' });
8 | var imgurAPI = "https://api.imgur.com/3/gallery/random/random/1";
9 | $.getJSON(imgurAPI).done(data =>
10 | dispatch({ type: 'IMAGES', data:data.data}))
11 | }
12 |
--------------------------------------------------------------------------------
/5. more examples/1. refactor/redux/middlewares/index.js:
--------------------------------------------------------------------------------
1 | export const crashReporter = store => next => action => {
2 | try{
3 | next(action);
4 | }catch(err){
5 | console.group('crashReporter');
6 | console.error('error happen with action == ', action);
7 | console.error(err);
8 | console.groupEnd('crashReporter');
9 | }
10 |
11 | }
--------------------------------------------------------------------------------
/5. more examples/1. refactor/redux/reducers/examples01/counter.js:
--------------------------------------------------------------------------------
1 | export default function counter(state = {result:0, loading:false}, action){
2 | switch (action.type) {
3 | case 'DECREMENT':
4 | return {...state,
5 | result: state.result - 1};
6 | default:
7 | return state;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/5. more examples/1. refactor/redux/reducers/examples01/images.js:
--------------------------------------------------------------------------------
1 | export default function images(state = {data:[],
2 | loading:"Please click the 'Random Images' button"}, action){
3 | switch (action.type) {
4 | case 'IMAGES':
5 | return {...state,
6 | data: action.data,
7 | loading: "loaded"
8 | };
9 | case 'IMAGES_LOADING':
10 | return {...state,
11 | loading: "loading..."
12 | };
13 | default:
14 | return state;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/5. more examples/1. refactor/redux/reducers/examples01/sum.js:
--------------------------------------------------------------------------------
1 | export default function sum(state = 3, action){
2 | switch (action.type) {
3 | case 'SUM':
4 | return parseInt(action.a) + parseInt(action.b);
5 | default:
6 | return state;
7 | }
8 | }
9 |
10 | function funcWithError(){
11 | throw Error('an error from sum')
12 | }
13 |
--------------------------------------------------------------------------------
/5. more examples/1. refactor/redux/reducers/index.js:
--------------------------------------------------------------------------------
1 | import counter from './examples01/counter'
2 | import images from './examples01/images'
3 | import sum from './examples01/sum'
4 | import { combineReducers } from 'redux'
5 | import {routerReducer } from 'react-router-redux'
6 |
7 | export default combineReducers({
8 | examples: combineReducers({
9 | count:counter,
10 | sum,
11 | images
12 | }),
13 | // todos: combineReducers({
14 |
15 | // }),
16 | // youtube: combineReducers({
17 |
18 | // }),
19 | routing: routerReducer
20 | })
--------------------------------------------------------------------------------
/5. more examples/1. refactor/redux/store/config.js:
--------------------------------------------------------------------------------
1 | import { createStore, applyMiddleware, compose} from 'redux'
2 | import combineReducer from '../reducers/index'
3 | import {crashReporter} from '../middlewares/index'
4 | import createLogger from 'redux-logger'
5 | import thunk from 'redux-thunk'
6 |
7 | const store = createStore(combineReducer, {}, compose(
8 | applyMiddleware(createLogger(), crashReporter, thunk),
9 | window.devToolsExtension ? window.devToolsExtension() : f => f
10 | ));
11 |
12 | export default store;
--------------------------------------------------------------------------------
/5. more examples/1. refactor/server.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack')
2 | var webpackDevMiddleware = require('webpack-dev-middleware')
3 | var webpackHotMiddleware = require('webpack-hot-middleware')
4 | var config = require('./webpack.config')
5 |
6 | var app = new (require('express'))()
7 | var port = 3000
8 |
9 | var compiler = webpack(config)
10 | app.use(webpackDevMiddleware(compiler, { noInfo: true, publicPath: config.output.publicPath }))
11 | app.use(webpackHotMiddleware(compiler))
12 |
13 | app.use(function(req, res) {
14 | res.sendFile(__dirname + '/index.html')
15 | })
16 |
17 | app.listen(port, function(error) {
18 | if (error) {
19 | console.error(error)
20 | } else {
21 | console.info("==> 🌎 Listening on port %s. Open up http://localhost:%s/ in your browser.", port, port)
22 | }
23 | })
24 |
--------------------------------------------------------------------------------
/5. more examples/1. refactor/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var webpack = require('webpack')
3 |
4 | module.exports = {
5 | devtool: 'cheap-module-eval-source-map',
6 | entry: [
7 | 'webpack-hot-middleware/client',
8 | './index'
9 | ],
10 | output: {
11 | path: path.join(__dirname, 'dist'),
12 | filename: 'bundle.js',
13 | publicPath: '/static/'
14 | },
15 | plugins: [
16 | new webpack.optimize.OccurenceOrderPlugin(),
17 | new webpack.HotModuleReplacementPlugin()
18 | ],
19 | module: {
20 | loaders: [
21 | {
22 | test: /\.js$/,
23 | loaders: [ 'babel' ],
24 | exclude: /node_modules/,
25 | include: __dirname
26 | }
27 | ]
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/5. more examples/2. todolist/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "react"],
3 | "plugins": ["transform-object-rest-spread"],
4 | "env": {
5 | "development": {
6 | "presets": ["react-hmre"]
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/5. more examples/2. todolist/components/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Link, browserHistory } from 'react-router'
3 |
4 | export default function App({ children }) {
5 | return (
6 |
7 |
8 | Links:
9 | {' '}
10 | Home
11 | {' '}
12 | Examples02
13 | {' '}
14 | Examples02 with parameter
15 |
16 |
17 |
18 | {' '}
19 |
20 | {' '}
21 |
22 |
23 |
24 |
{children}
25 |
26 | )
27 | }
--------------------------------------------------------------------------------
/5. more examples/2. todolist/components/Examples.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import Counter from '../containers/examples01/Counter'
3 | import Sum from '../containers/examples01/Sum'
4 | import RandomImages from '../containers/examples01/RandomImages'
5 |
6 | export default class Examples extends Component {
7 | constructor(props) {
8 | super(props)
9 | }
10 | render() {
11 | return (
12 |
13 |
React
14 |
15 |
16 |
17 |
18 | )
19 | }
20 | }
--------------------------------------------------------------------------------
/5. more examples/2. todolist/components/Examples02.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 |
3 | export default class Examples02 extends Component {
4 | constructor(props) {
5 | super(props)
6 | }
7 | render() {
8 | console.log(this.props);
9 | return (
10 |
11 |
Examples 02
12 | Hello, {this.props.params.name || 'world'}
13 |
14 | )
15 | }
16 | }
--------------------------------------------------------------------------------
/5. more examples/2. todolist/components/Todos.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import AddTodo from '../containers/todos/AddTodo'
3 | import TodosList from '../containers/todos/TodosList'
4 | import FiltersList from '../containers/todos/FiltersList'
5 |
6 | export default class Todos extends Component {
7 | render() {
8 | return (
9 |
10 |
Todo List
11 |
12 |
13 |
14 |
15 | )
16 | }
17 | }
--------------------------------------------------------------------------------
/5. more examples/2. todolist/components/Youtube.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 |
3 | export default class Youtube extends Component {
4 | render() {
5 | return (
6 |
7 |
Youtube
8 |
9 | )
10 | }
11 | }
--------------------------------------------------------------------------------
/5. more examples/2. todolist/containers/examples01/Counter.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { connect } from 'react-redux'
3 | import { decrease } from '../../redux/actions/index'
4 | class Counter extends Component{
5 | constructor(props) {
6 | super(props)
7 | }
8 | render() {
9 | const {count:{result},onDecrement} = this.props;
10 | return (
11 |
12 | Clicked:
{result} times
13 |
14 |
15 |
16 | )
17 | }
18 | }
19 |
20 | export default connect(
21 | (state, ownProps) => ({
22 | count: state.examples.count,
23 | prop2: state.prop // just an example in case of many properties
24 | }),
25 | {
26 | onDecrement: decrease,
27 | func2: () => {} // just an example in case you need many functions from dispatch
28 | }
29 | )(Counter)
--------------------------------------------------------------------------------
/5. more examples/2. todolist/containers/examples01/RandomImages.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { connect } from 'react-redux'
3 | import { getRandomImages } from '../../redux/actions/index'
4 |
5 | class RandomImages extends Component{
6 | constructor(props) {
7 | super(props)
8 | }
9 | render() {
10 | const {images:{loading, data},onRandomImages} = this.props;
11 | return (
12 |
13 |
15 |
CountStatus:
16 |
17 | {loading}
18 |
19 |
20 |
21 | )
22 | }
23 | }
24 | function ImageList(props) {
25 | return (
26 |
27 | {props.images.map((image)=>
28 |

)}
31 |
32 | )
33 | }
34 |
35 | export default connect(
36 | (state, ownProps) =>( {
37 | images: state.examples.images
38 | }),
39 | {onRandomImages: () => getRandomImages}
40 | )(RandomImages)
--------------------------------------------------------------------------------
/5. more examples/2. todolist/containers/examples01/Sum.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { getSum } from '../../redux/actions/index'
3 | import React, { Component } from 'react'
4 |
5 | class Sum extends Component{
6 | constructor(props) {
7 | super(props)
8 | this.state = {a:1, b: 2}
9 | }
10 | render() {
11 | const {state:{a,b}, props:{sum, onSum}} = this;
12 | return (
13 |
14 |
this.setState({a: e.target.value})}/>
16 | +
this.setState({b: e.target.value})}/>
18 | =
{sum}
19 |
20 |
21 |
22 | )
23 | }
24 | }
25 |
26 | export default connect(
27 | (state, ownProps) => ( {
28 | sum: state.examples.sum
29 | }),
30 | {onSum: getSum}
31 | )(Sum)
--------------------------------------------------------------------------------
/5. more examples/2. todolist/containers/todos/AddTodo.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { connect } from 'react-redux'
3 | import { addTodo } from '../../redux/actions/todos'
4 | class AddTodo extends Component {
5 | constructor(props) {
6 | super(props)
7 | this.state = {todo: ""};
8 | }
9 | render() {
10 | const {state: {todo}} = this;
11 | const onAddTodo = (e) => {
12 | e.preventDefault()
13 | if (!todo.trim()) {
14 | return
15 | }
16 | this.props.addTodo(todo);
17 | this.setState({todo: ''})
18 | }
19 | return (
20 |
21 |
28 |
29 | )
30 | }
31 | }
32 |
33 | export default connect(null,{
34 | addTodo
35 | })(AddTodo)
36 |
--------------------------------------------------------------------------------
/5. more examples/2. todolist/containers/todos/Filter.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react'
2 | import { setTodoFilter } from '../../redux/actions/todos'
3 | import { connect } from 'react-redux'
4 |
5 | const Filter = ({ active, children, onFilter }) => {
6 | if (active) {
7 | return {children}
8 | }
9 |
10 | return (
11 | {
13 | e.preventDefault()
14 | onFilter()
15 | }}
16 | >
17 | {children}
18 |
19 | )
20 | }
21 |
22 | Filter.propTypes = {
23 | active: PropTypes.bool.isRequired,
24 | children: PropTypes.node.isRequired,
25 | onFilter: PropTypes.func.isRequired
26 | }
27 |
28 | export default connect(
29 | (state, ownProps) => {
30 | return {
31 | active: state.todos.todosFilter === ownProps.filter
32 | }
33 | },
34 | (dispatch, ownProps) => {
35 | return {
36 | onFilter: () => {
37 | dispatch(setTodoFilter(ownProps.filter))
38 | }
39 | }
40 | }
41 | )(Filter)
42 |
--------------------------------------------------------------------------------
/5. more examples/2. todolist/containers/todos/FiltersList.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Filter from './Filter'
3 |
4 | const FiltersList = () => (
5 |
6 | Show:
7 | {" "}
8 |
9 | All
10 |
11 | {", "}
12 |
13 | Active
14 |
15 | {", "}
16 |
17 | Completed
18 |
19 |
20 | )
21 | export default FiltersList
--------------------------------------------------------------------------------
/5. more examples/2. todolist/containers/todos/Todo.js:
--------------------------------------------------------------------------------
1 | import React, {Component, PropTypes } from 'react'
2 | import { toggleTodo } from '../../redux/actions/todos'
3 | import { connect } from 'react-redux'
4 |
5 | const Todo = ({id, toggleTodo, completed, text}) => (
6 | toggleTodo(id) }
8 | style={{
9 | textDecoration: completed ? 'line-through' : 'none'
10 | }}
11 | >
12 | {text}
13 |
14 | )
15 |
16 | Todo.propTypes = {
17 | toggleTodo: PropTypes.func.isRequired,
18 | completed: PropTypes.bool.isRequired,
19 | text: PropTypes.string.isRequired
20 | }
21 |
22 | export default connect(
23 | null,
24 | {
25 | toggleTodo
26 | }
27 | )(Todo)
--------------------------------------------------------------------------------
/5. more examples/2. todolist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | React example
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/5. more examples/2. todolist/redux/actions/index.js:
--------------------------------------------------------------------------------
1 | import $ from 'jquery'
2 | export const decrease = () => ({ type: 'DECREMENT' });
3 |
4 | export const getSum = (a, b) => ({ type: 'SUM', a, b });
5 |
6 | export const getRandomImages = (dispatch, state) => {
7 | dispatch({ type: 'IMAGES_LOADING' });
8 | var imgurAPI = "https://api.imgur.com/3/gallery/random/random/1";
9 | $.getJSON(imgurAPI).done(data =>
10 | dispatch({ type: 'IMAGES', data:data.data}))
11 | }
12 |
--------------------------------------------------------------------------------
/5. more examples/2. todolist/redux/actions/todos.js:
--------------------------------------------------------------------------------
1 | let nextTodoId = 0
2 | export const addTodo = (text) => {
3 | return {
4 | type: 'ADD_TODO',
5 | id: nextTodoId++,
6 | text
7 | }
8 | }
9 |
10 | export const setTodoFilter = (filter) => {
11 | return {
12 | type: 'SET_TODOS_FILTER',
13 | filter
14 | }
15 | }
16 |
17 | export const toggleTodo = (id) => {
18 | return {
19 | type: 'TOGGLE_TODO',
20 | id
21 | }
22 | }
--------------------------------------------------------------------------------
/5. more examples/2. todolist/redux/middlewares/index.js:
--------------------------------------------------------------------------------
1 | export const crashReporter = store => next => action => {
2 | try{
3 | next(action);
4 | }catch(err){
5 | console.group('crashReporter');
6 | console.error('error happen with action == ', action);
7 | console.error(err);
8 | console.groupEnd('crashReporter');
9 | }
10 |
11 | }
--------------------------------------------------------------------------------
/5. more examples/2. todolist/redux/reducers/examples01/counter.js:
--------------------------------------------------------------------------------
1 | export default function counter(state = {result:0, loading:false}, action){
2 | switch (action.type) {
3 | case 'DECREMENT':
4 | return {...state,
5 | result: state.result - 1};
6 | default:
7 | return state;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/5. more examples/2. todolist/redux/reducers/examples01/images.js:
--------------------------------------------------------------------------------
1 | export default function images(state = {data:[],
2 | loading:"Please click the 'Random Images' button"}, action){
3 | switch (action.type) {
4 | case 'IMAGES':
5 | return {...state,
6 | data: action.data,
7 | loading: "loaded"
8 | };
9 | case 'IMAGES_LOADING':
10 | return {...state,
11 | loading: "loading..."
12 | };
13 | default:
14 | return state;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/5. more examples/2. todolist/redux/reducers/examples01/sum.js:
--------------------------------------------------------------------------------
1 | export default function sum(state = 3, action){
2 | switch (action.type) {
3 | case 'SUM':
4 | return parseInt(action.a) + parseInt(action.b);
5 | default:
6 | return state;
7 | }
8 | }
9 |
10 | function funcWithError(){
11 | throw Error('an error from sum')
12 | }
13 |
--------------------------------------------------------------------------------
/5. more examples/2. todolist/redux/reducers/index.js:
--------------------------------------------------------------------------------
1 | import counter from './examples01/counter'
2 | import images from './examples01/images'
3 | import sum from './examples01/sum'
4 |
5 | import todosList from './todos/todosList'
6 | import todosFilter from './todos/todosFilter'
7 |
8 | import { combineReducers } from 'redux'
9 | import {routerReducer } from 'react-router-redux'
10 |
11 | export default combineReducers({
12 | examples: combineReducers({
13 | count:counter,
14 | sum,
15 | images
16 | }),
17 | todos: combineReducers({
18 | todosList,
19 | todosFilter
20 | }),
21 | // youtube: combineReducers({
22 | // }),
23 | routing: routerReducer
24 | })
--------------------------------------------------------------------------------
/5. more examples/2. todolist/redux/reducers/todos/todosFilter.js:
--------------------------------------------------------------------------------
1 | const todosFilter = (state = 'SHOW_ALL', action) => {
2 | switch (action.type) {
3 | case 'SET_TODOS_FILTER':
4 | return action.filter
5 | default:
6 | return state
7 | }
8 | }
9 |
10 | export default todosFilter
11 |
--------------------------------------------------------------------------------
/5. more examples/2. todolist/redux/reducers/todos/todosList.js:
--------------------------------------------------------------------------------
1 | export default function (state = [], action) {
2 | switch (action.type) {
3 | case 'ADD_TODO':
4 | const newTodo = {
5 | id: action.id,
6 | text: action.text,
7 | completed: false
8 | }
9 | return [
10 | ...state,
11 | newTodo
12 | ]
13 | case 'TOGGLE_TODO':
14 | return state.map(todo => {
15 | if (todo.id !== action.id) {
16 | return todo
17 | }
18 |
19 | return Object.assign({}, todo, {
20 | completed: !todo.completed
21 | })
22 | })
23 | default:
24 | return state
25 | }
26 | }
--------------------------------------------------------------------------------
/5. more examples/2. todolist/redux/store/config.js:
--------------------------------------------------------------------------------
1 | import { createStore, applyMiddleware, compose} from 'redux'
2 | import combineReducer from '../reducers/index'
3 | import {crashReporter} from '../middlewares/index'
4 | import createLogger from 'redux-logger'
5 | import thunk from 'redux-thunk'
6 |
7 | const store = createStore(combineReducer, {}, compose(
8 | applyMiddleware(createLogger(), crashReporter, thunk),
9 | window.devToolsExtension ? window.devToolsExtension() : f => f
10 | ));
11 |
12 | export default store;
--------------------------------------------------------------------------------
/5. more examples/2. todolist/server.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack')
2 | var webpackDevMiddleware = require('webpack-dev-middleware')
3 | var webpackHotMiddleware = require('webpack-hot-middleware')
4 | var config = require('./webpack.config')
5 |
6 | var app = new (require('express'))()
7 | var port = 3000
8 |
9 | var compiler = webpack(config)
10 | app.use(webpackDevMiddleware(compiler, { noInfo: true, publicPath: config.output.publicPath }))
11 | app.use(webpackHotMiddleware(compiler))
12 |
13 | app.use(function(req, res) {
14 | res.sendFile(__dirname + '/index.html')
15 | })
16 |
17 | app.listen(port, function(error) {
18 | if (error) {
19 | console.error(error)
20 | } else {
21 | console.info("==> 🌎 Listening on port %s. Open up http://localhost:%s/ in your browser.", port, port)
22 | }
23 | })
24 |
--------------------------------------------------------------------------------
/5. more examples/2. todolist/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var webpack = require('webpack')
3 |
4 | module.exports = {
5 | devtool: 'cheap-module-eval-source-map',
6 | entry: [
7 | 'webpack-hot-middleware/client',
8 | './index'
9 | ],
10 | output: {
11 | path: path.join(__dirname, 'dist'),
12 | filename: 'bundle.js',
13 | publicPath: '/static/'
14 | },
15 | plugins: [
16 | new webpack.optimize.OccurenceOrderPlugin(),
17 | new webpack.HotModuleReplacementPlugin()
18 | ],
19 | module: {
20 | loaders: [
21 | {
22 | test: /\.js$/,
23 | loaders: [ 'babel' ],
24 | exclude: /node_modules/,
25 | include: __dirname
26 | }
27 | ]
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/5. more examples/3. youtube/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "react"],
3 | "plugins": ["transform-object-rest-spread"],
4 | "env": {
5 | "development": {
6 | "presets": ["react-hmre"]
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/5. more examples/3. youtube/components/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Link, browserHistory } from 'react-router'
3 |
4 | export default function App({ children }) {
5 | return (
6 |
7 |
8 | Links:
9 | {' '}
10 | Home
11 | {' '}
12 | Examples02
13 | {' '}
14 | Examples02 with parameter
15 |
16 |
17 |
18 | {' '}
19 |
20 | {' '}
21 |
22 |
23 |
24 |
{children}
25 |
26 | )
27 | }
--------------------------------------------------------------------------------
/5. more examples/3. youtube/components/Examples.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import Counter from '../containers/examples01/Counter'
3 | import Sum from '../containers/examples01/Sum'
4 | import RandomImages from '../containers/examples01/RandomImages'
5 |
6 | export default class Examples extends Component {
7 | constructor(props) {
8 | super(props)
9 | }
10 | render() {
11 | return (
12 |
13 |
React
14 |
15 |
16 |
17 |
18 | )
19 | }
20 | }
--------------------------------------------------------------------------------
/5. more examples/3. youtube/components/Examples02.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 |
3 | export default class Examples02 extends Component {
4 | constructor(props) {
5 | super(props)
6 | }
7 | render() {
8 | console.log(this.props);
9 | return (
10 |
11 |
Examples 02
12 | Hello, {this.props.params.name || 'world'}
13 |
14 | )
15 | }
16 | }
--------------------------------------------------------------------------------
/5. more examples/3. youtube/components/Todos.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import AddTodo from '../containers/todos/AddTodo'
3 | import TodosList from '../containers/todos/TodosList'
4 | import FiltersList from '../containers/todos/FiltersList'
5 |
6 | export default class Todos extends Component {
7 | render() {
8 | return (
9 |
10 |
Todo List
11 |
12 |
13 |
14 |
15 | )
16 | }
17 | }
--------------------------------------------------------------------------------
/5. more examples/3. youtube/components/Youtube.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import Search from '../containers/youtube/Search'
3 | import Video from '../containers/youtube/Video'
4 | import List from '../containers/youtube/List'
5 |
6 | export default class Youtube extends Component {
7 | render() {
8 | return (
9 |
10 |
Youtube
11 |
12 |
13 |
14 |
15 | )
16 | }
17 | }
--------------------------------------------------------------------------------
/5. more examples/3. youtube/containers/examples01/Counter.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { connect } from 'react-redux'
3 | import { decrease } from '../../redux/actions/index'
4 | class Counter extends Component{
5 | constructor(props) {
6 | super(props)
7 | }
8 | render() {
9 | const {count:{result},onDecrement} = this.props;
10 | return (
11 |
12 | Clicked:
{result} times
13 |
14 |
15 |
16 | )
17 | }
18 | }
19 |
20 | export default connect(
21 | (state, ownProps) => ({
22 | count: state.examples.count,
23 | prop2: state.prop // just an example in case of many properties
24 | }),
25 | {
26 | onDecrement: decrease,
27 | func2: () => {} // just an example in case you need many functions from dispatch
28 | }
29 | )(Counter)
--------------------------------------------------------------------------------
/5. more examples/3. youtube/containers/examples01/RandomImages.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { connect } from 'react-redux'
3 | import { getRandomImages } from '../../redux/actions/index'
4 |
5 | class RandomImages extends Component{
6 | constructor(props) {
7 | super(props)
8 | }
9 | render() {
10 | const {images:{loading, data},onRandomImages} = this.props;
11 | return (
12 |
13 |
15 |
CountStatus:
16 |
17 | {loading}
18 |
19 |
20 |
21 | )
22 | }
23 | }
24 | function ImageList(props) {
25 | return (
26 |
27 | {props.images.map((image)=>
28 |

)}
31 |
32 | )
33 | }
34 |
35 | export default connect(
36 | (state, ownProps) =>( {
37 | images: state.examples.images
38 | }),
39 | {onRandomImages: () => getRandomImages}
40 | )(RandomImages)
--------------------------------------------------------------------------------
/5. more examples/3. youtube/containers/examples01/Sum.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { getSum } from '../../redux/actions/index'
3 | import React, { Component } from 'react'
4 |
5 | class Sum extends Component{
6 | constructor(props) {
7 | super(props)
8 | this.state = {a:1, b: 2}
9 | }
10 | render() {
11 | const {state:{a,b}, props:{sum, onSum}} = this;
12 | return (
13 |
14 |
this.setState({a: e.target.value})}/>
16 | +
this.setState({b: e.target.value})}/>
18 | =
{sum}
19 |
20 |
21 |
22 | )
23 | }
24 | }
25 |
26 | export default connect(
27 | (state, ownProps) => ( {
28 | sum: state.examples.sum
29 | }),
30 | {onSum: getSum}
31 | )(Sum)
--------------------------------------------------------------------------------
/5. more examples/3. youtube/containers/todos/AddTodo.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { connect } from 'react-redux'
3 | import { addTodo } from '../../redux/actions/todos'
4 | class AddTodo extends Component {
5 | constructor(props) {
6 | super(props)
7 | this.state = {todo: ""};
8 | }
9 | render() {
10 | const {state: {todo}} = this;
11 | const onAddTodo = (e) => {
12 | e.preventDefault()
13 | if (!todo.trim()) {
14 | return
15 | }
16 | this.props.addTodo(todo);
17 | this.setState({todo: ''})
18 | }
19 | return (
20 |
21 |
28 |
29 | )
30 | }
31 | }
32 |
33 | export default connect(null,{
34 | addTodo
35 | })(AddTodo)
36 |
--------------------------------------------------------------------------------
/5. more examples/3. youtube/containers/todos/Filter.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react'
2 | import { setTodoFilter } from '../../redux/actions/todos'
3 | import { connect } from 'react-redux'
4 |
5 | const Filter = ({ active, children, onFilter }) => {
6 | if (active) {
7 | return {children}
8 | }
9 |
10 | return (
11 | {
13 | e.preventDefault()
14 | onFilter()
15 | }}
16 | >
17 | {children}
18 |
19 | )
20 | }
21 |
22 | Filter.propTypes = {
23 | active: PropTypes.bool.isRequired,
24 | children: PropTypes.node.isRequired,
25 | onFilter: PropTypes.func.isRequired
26 | }
27 |
28 | export default connect(
29 | (state, ownProps) => {
30 | return {
31 | active: state.todos.todosFilter === ownProps.filter
32 | }
33 | },
34 | (dispatch, ownProps) => {
35 | return {
36 | onFilter: () => {
37 | dispatch(setTodoFilter(ownProps.filter))
38 | }
39 | }
40 | }
41 | )(Filter)
42 |
--------------------------------------------------------------------------------
/5. more examples/3. youtube/containers/todos/FiltersList.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Filter from './Filter'
3 |
4 | const FiltersList = () => (
5 |
6 | Show:
7 | {" "}
8 |
9 | All
10 |
11 | {", "}
12 |
13 | Active
14 |
15 | {", "}
16 |
17 | Completed
18 |
19 |
20 | )
21 | export default FiltersList
--------------------------------------------------------------------------------
/5. more examples/3. youtube/containers/todos/Todo.js:
--------------------------------------------------------------------------------
1 | import React, {Component, PropTypes } from 'react'
2 | import { toggleTodo } from '../../redux/actions/todos'
3 | import { connect } from 'react-redux'
4 |
5 | const Todo = ({id, toggleTodo, completed, text}) => (
6 | toggleTodo(id) }
8 | style={{
9 | textDecoration: completed ? 'line-through' : 'none'
10 | }}
11 | >
12 | {text}
13 |
14 | )
15 |
16 | Todo.propTypes = {
17 | toggleTodo: PropTypes.func.isRequired,
18 | completed: PropTypes.bool.isRequired,
19 | text: PropTypes.string.isRequired
20 | }
21 |
22 | export default connect(
23 | null,
24 | {
25 | toggleTodo
26 | }
27 | )(Todo)
--------------------------------------------------------------------------------
/5. more examples/3. youtube/containers/youtube/List.js:
--------------------------------------------------------------------------------
1 | import React, {Component, PropTypes } from 'react'
2 | import { connect } from 'react-redux'
3 | import ListItem from './ListItem'
4 |
5 | class List extends Component {
6 | render() {
7 | const {props:{list}} = this;
8 | return (
9 |
10 | {
11 | list.map(video => {
12 | const { id:{videoId} } = video;
13 | return()
14 | })
15 | }
16 |
17 | )
18 | }
19 | }
20 |
21 | export default connect( (state) =>({
22 | list: state.youtube.youtubeList
23 | })
24 | )(List)
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/5. more examples/3. youtube/containers/youtube/ListItem.js:
--------------------------------------------------------------------------------
1 | import React, {Component, PropTypes } from 'react'
2 | import { connect } from 'react-redux'
3 | import {setVideo } from '../../redux/actions/youtube'
4 |
5 |
6 | class ListItem extends Component {
7 | render() {
8 | const { id: {videoId},
9 | snippet: {title, description, thumbnails: {default: {url}}}} = this.props.video;
10 | const onVideo = (event) => {
11 | event.preventDefault();
12 | this.props.setVideo(this.props.video)
13 | window.scrollTo(0, 0);
14 | }
15 | return (
16 |
17 | {title}
18 | {description}
19 |
20 |
21 | )
22 | }
23 | }
24 |
25 | export default connect(null,
26 | {
27 | setVideo
28 | }
29 | )(ListItem)
--------------------------------------------------------------------------------
/5. more examples/3. youtube/containers/youtube/Search.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { connect } from 'react-redux'
3 | import {search } from '../../redux/actions/youtube'
4 | class Search extends Component {
5 | constructor(props) {
6 | super(props)
7 | this.state = {term: ""}
8 | }
9 | render() {
10 | const {state:{term}} = this;
11 | const onSetTerm = (e) => {
12 | e.preventDefault()
13 | this.props.onSearch(term);
14 | }
15 | return (
16 |
17 |
24 |
25 | )
26 | }
27 | }
28 | function mapDispatchToProps(dispatch){
29 | return {onSearch: (term) => dispatch(search.bind(null,term))}
30 | }
31 | export default connect(null,
32 | mapDispatchToProps
33 | )(Search)
34 |
--------------------------------------------------------------------------------
/5. more examples/3. youtube/containers/youtube/Video.js:
--------------------------------------------------------------------------------
1 | import React, {Component, PropTypes } from 'react'
2 | import { connect } from 'react-redux'
3 | class Video extends Component {
4 | render() {
5 | const {props:{video}} = this;
6 | if(!video){
7 | return
8 | }
9 | const { id:{videoId} } = video;
10 | return (
11 |
12 |
13 |
17 |
18 | )
19 | }
20 | }
21 |
22 | export default connect( (state)=>({
23 | video: state.youtube.video
24 | }),
25 | null
26 | )(Video)
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/5. more examples/3. youtube/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | React example
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/5. more examples/3. youtube/redux/actions/index.js:
--------------------------------------------------------------------------------
1 | import $ from 'jquery'
2 | export const decrease = () => ({ type: 'DECREMENT' });
3 |
4 | export const getSum = (a, b) => ({ type: 'SUM', a, b });
5 |
6 | export const getRandomImages = (dispatch, state) => {
7 | dispatch({ type: 'IMAGES_LOADING' });
8 | var imgurAPI = "https://api.imgur.com/3/gallery/random/random/1";
9 | $.getJSON(imgurAPI).done(data =>
10 | dispatch({ type: 'IMAGES', data:data.data}))
11 | }
12 |
--------------------------------------------------------------------------------
/5. more examples/3. youtube/redux/actions/todos.js:
--------------------------------------------------------------------------------
1 | let nextTodoId = 0
2 | export const addTodo = (text) => {
3 | return {
4 | type: 'ADD_TODO',
5 | id: nextTodoId++,
6 | text
7 | }
8 | }
9 |
10 | export const setTodoFilter = (filter) => {
11 | return {
12 | type: 'SET_TODOS_FILTER',
13 | filter
14 | }
15 | }
16 |
17 | export const toggleTodo = (id) => {
18 | return {
19 | type: 'TOGGLE_TODO',
20 | id
21 | }
22 | }
--------------------------------------------------------------------------------
/5. more examples/3. youtube/redux/actions/youtube.js:
--------------------------------------------------------------------------------
1 | import $ from 'jquery'
2 | export const setList = (list) => ({ type: 'YOUTUBE_SEARCH_LOADED', list });
3 | export const setTerm = () => ({ type: 'YOUTUBE_TERM' });
4 | export const setVideo = (video) => ({ type: 'YOUTUBE_VIDEO', video });
5 |
6 | export const search = (term, dispatch, state) => {
7 | dispatch( {type: 'YOUTUBE_SEARCH_LOADING'} );
8 | const MAX = 20;
9 | const API_KEY = 'AIzaSyAY7wfv-FJ965RdnPjAxXNScS0VyJmsvZo';
10 | let api = 'https://www.googleapis.com/youtube/v3/search';
11 | api = `${api}?part=snippet&q=${term}&maxResults=${MAX}&order=viewCount&key=${API_KEY}`;
12 | $.getJSON(api).done(data =>{
13 | const list = data.items.filter( (d) => d.id && d.id.videoId );
14 | dispatch(setList(list));
15 | dispatch(setVideo(null));
16 | })
17 | }
--------------------------------------------------------------------------------
/5. more examples/3. youtube/redux/middlewares/index.js:
--------------------------------------------------------------------------------
1 | export const crashReporter = store => next => action => {
2 | try{
3 | next(action);
4 | }catch(err){
5 | console.group('crashReporter');
6 | console.error('error happen with action == ', action);
7 | console.error(err);
8 | console.groupEnd('crashReporter');
9 | }
10 |
11 | }
--------------------------------------------------------------------------------
/5. more examples/3. youtube/redux/reducers/examples01/counter.js:
--------------------------------------------------------------------------------
1 | export default function counter(state = {result:0, loading:false}, action){
2 | switch (action.type) {
3 | case 'DECREMENT':
4 | return {...state,
5 | result: state.result - 1};
6 | default:
7 | return state;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/5. more examples/3. youtube/redux/reducers/examples01/images.js:
--------------------------------------------------------------------------------
1 | export default function images(state = {data:[],
2 | loading:"Please click the 'Random Images' button"}, action){
3 | switch (action.type) {
4 | case 'IMAGES':
5 | return {...state,
6 | data: action.data,
7 | loading: "loaded"
8 | };
9 | case 'IMAGES_LOADING':
10 | return {...state,
11 | loading: "loading..."
12 | };
13 | default:
14 | return state;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/5. more examples/3. youtube/redux/reducers/examples01/sum.js:
--------------------------------------------------------------------------------
1 | export default function sum(state = 3, action){
2 | switch (action.type) {
3 | case 'SUM':
4 | return parseInt(action.a) + parseInt(action.b);
5 | default:
6 | return state;
7 | }
8 | }
9 |
10 | function funcWithError(){
11 | throw Error('an error from sum')
12 | }
13 |
--------------------------------------------------------------------------------
/5. more examples/3. youtube/redux/reducers/index.js:
--------------------------------------------------------------------------------
1 | import counter from './examples01/counter'
2 | import images from './examples01/images'
3 | import sum from './examples01/sum'
4 |
5 | import todosList from './todos/todosList'
6 | import todosFilter from './todos/todosFilter'
7 |
8 | import youtubeList from './youtube/list'
9 | import youtubeVideo from './youtube/video'
10 | import youtubeLoad from './youtube/load'
11 |
12 | import { combineReducers } from 'redux'
13 | import {routerReducer } from 'react-router-redux'
14 |
15 | export default combineReducers({
16 | examples: combineReducers({
17 | count:counter,
18 | sum,
19 | images
20 | }),
21 | todos: combineReducers({
22 | todosList,
23 | todosFilter
24 | }),
25 | youtube: combineReducers({
26 | youtubeList,
27 | video: youtubeVideo,
28 | load: youtubeLoad
29 | }),
30 | routing: routerReducer
31 | })
--------------------------------------------------------------------------------
/5. more examples/3. youtube/redux/reducers/todos/todosFilter.js:
--------------------------------------------------------------------------------
1 | const todosFilter = (state = 'SHOW_ALL', action) => {
2 | switch (action.type) {
3 | case 'SET_TODOS_FILTER':
4 | return action.filter
5 | default:
6 | return state
7 | }
8 | }
9 |
10 | export default todosFilter
11 |
--------------------------------------------------------------------------------
/5. more examples/3. youtube/redux/reducers/todos/todosList.js:
--------------------------------------------------------------------------------
1 | export default function (state = [], action) {
2 | switch (action.type) {
3 | case 'ADD_TODO':
4 | const newTodo = {
5 | id: action.id,
6 | text: action.text,
7 | completed: false
8 | }
9 | return [
10 | ...state,
11 | newTodo
12 | ]
13 | case 'TOGGLE_TODO':
14 | return state.map(todo => {
15 | if (todo.id !== action.id) {
16 | return todo
17 | }
18 |
19 | return Object.assign({}, todo, {
20 | completed: !todo.completed
21 | })
22 | })
23 | default:
24 | return state
25 | }
26 | }
--------------------------------------------------------------------------------
/5. more examples/3. youtube/redux/reducers/youtube/list.js:
--------------------------------------------------------------------------------
1 | export default (state = [], action) => {
2 | switch (action.type) {
3 | case 'YOUTUBE_SEARCH_LOADED':
4 | return action.list
5 | default:
6 | return state
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/5. more examples/3. youtube/redux/reducers/youtube/load.js:
--------------------------------------------------------------------------------
1 | export default (state = 'not search yet', action) => {
2 | switch (action.type) {
3 | case 'YOUTUBE_SEARCH_LOADING':
4 | return 'loading'
5 | case 'YOUTUBE_SEARCH_LOADED':
6 | return 'loaded'
7 | default:
8 | return state
9 | }
10 | }
--------------------------------------------------------------------------------
/5. more examples/3. youtube/redux/reducers/youtube/video.js:
--------------------------------------------------------------------------------
1 | export default (state = null, action) => {
2 | switch (action.type) {
3 | case 'YOUTUBE_VIDEO':
4 | return action.video
5 | default:
6 | return state
7 | }
8 | }
--------------------------------------------------------------------------------
/5. more examples/3. youtube/redux/store/config.js:
--------------------------------------------------------------------------------
1 | import { createStore, applyMiddleware, compose} from 'redux'
2 | import combineReducer from '../reducers/index'
3 | import {crashReporter} from '../middlewares/index'
4 | import createLogger from 'redux-logger'
5 | import thunk from 'redux-thunk'
6 |
7 | const store = createStore(combineReducer, {}, compose(
8 | applyMiddleware(createLogger(), crashReporter, thunk),
9 | window.devToolsExtension ? window.devToolsExtension() : f => f
10 | ));
11 |
12 | export default store;
--------------------------------------------------------------------------------
/5. more examples/3. youtube/server.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack')
2 | var webpackDevMiddleware = require('webpack-dev-middleware')
3 | var webpackHotMiddleware = require('webpack-hot-middleware')
4 | var config = require('./webpack.config')
5 |
6 | var app = new (require('express'))()
7 | var port = 3000
8 |
9 | var compiler = webpack(config)
10 | app.use(webpackDevMiddleware(compiler, { noInfo: true, publicPath: config.output.publicPath }))
11 | app.use(webpackHotMiddleware(compiler))
12 |
13 | app.use(function(req, res) {
14 | res.sendFile(__dirname + '/index.html')
15 | })
16 |
17 | app.listen(port, function(error) {
18 | if (error) {
19 | console.error(error)
20 | } else {
21 | console.info("==> 🌎 Listening on port %s. Open up http://localhost:%s/ in your browser.", port, port)
22 | }
23 | })
24 |
--------------------------------------------------------------------------------
/5. more examples/3. youtube/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var webpack = require('webpack')
3 |
4 | module.exports = {
5 | devtool: 'cheap-module-eval-source-map',
6 | entry: [
7 | 'webpack-hot-middleware/client',
8 | './index'
9 | ],
10 | output: {
11 | path: path.join(__dirname, 'dist'),
12 | filename: 'bundle.js',
13 | publicPath: '/static/'
14 | },
15 | plugins: [
16 | new webpack.optimize.OccurenceOrderPlugin(),
17 | new webpack.HotModuleReplacementPlugin()
18 | ],
19 | module: {
20 | loaders: [
21 | {
22 | test: /\.js$/,
23 | loaders: [ 'babel' ],
24 | exclude: /node_modules/,
25 | include: __dirname
26 | }
27 | ]
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # redux-ld
2 | This git repository is created for the course "React Redux React-Router: From Beginner to Paid Professional" in https://www.udemy.com/react-redux-react-router/
3 |
--------------------------------------------------------------------------------