Category Archives: reactjs

React and Redux Sagas Weather Report App Tutorial

Overview

In this tutorial we’re going to build a weather Report by using React Boilerplate . Few months ago I did a code testing by using angualr1.5 and now I like to do it again by using current popular tools react, redux and sagas.  React Boilerplate is not for beginner level, and I won’t explain any concept of react, redux, and sagas. There already has too many tutorial about it.

React Boilerplate is very mature start setup for  building scalable react app and suit for any complex real life project.

After finish that should look like this:

Screen Shot 2018-01-19 at 4.06.00 pm

Now let start it:

Part 1 – Setting up the base project and template.

  1. Create a folder, named “weather-react-redux-saga-app”
  2. cd weather-react-redux-saga-app
  3. run git clone https://github.com/react-boilerplate/react-boilerplate.git .
  4. npm run setup ( install the package and start the project.)
  5. npm run clean ( get rid of the template that react boilerplate provides)
  6. npm start ( now project setup done)

Part 2 – Create the container and components by  using React Boilerplate  provide component generate command. I will create one container component and two stateless component (WeaterListContainer and WeatherList stateless component and Weather component).

  1. run command ‘npm run generate container

move the arrow select React.component

what should it be called?

Do you want headers?

Do you want an actions/constants/selectors/reducer tuple for this container? y

Do you want sagas for asynchronous flows?y

Do you want i18n messages (i.e. will this component use text)?n

Do you want to load resources asynchronously?n

  2 . run command ‘npm run generate component

move the arrow select Stateless Function then enter

       What should it be called? WeatherList

Do you want i18n messages (i.e. will this component use text)?n

 Do you want to load the component asynchronously? n

  follow step 2 create Weather component.

  3. go to HomePage/index edit it using the WeatherListContainer

Screen Shot 2018-01-22 at 2.02.31 pm

Next post will explain how to working with api: openweathermap to get data by using saga and display it to the page.

to be continue….

 

Advertisements

React & ES6 project dev enviroment setup

In this day, the JavaScript project set up it was a big complex, and this tutorial will show you how to set up the environment for build react SPA working with ES6.

First, create package.json file, here is the common using packages I was included, and I will use npm start to run the project instead of gulp. so the packages has included the scripts part with in it.


{
  "name": "react-Demo",
  "version": "1.0.0",
  "description": "react kit for React and es6 demo project",
  "scripts": {
    "prestart":"babel-node tools/startMessage.js",
    "start":"npm-run-all --parallel test:watch open:src lint:watch",
    "open:src": "babel-node tools/srcServer.js",
    "lint": "node_modules/.bin/esw webpack.config.* src tools",
    "lint:watch": "npm run lint -- --watch",
    "test": "mocha --reporter progress tools/testSetup.js \"src/**/*.spec.js\"",
    "test:watch": "npm run test -- --watch"
  },
  "author": "Sandy Zhang",
  "license": "MIT",
  "dependencies": {
    "babel-polyfill": "6.8.0",
    "bootstrap": "3.3.6",
    "jquery": "2.2.3",
    "react": "15.0.2",
    "react-dom": "15.0.2",
    "react-redux": "4.4.5",
    "react-router": "2.4.0",
    "react-router-redux": "4.0.4",
    "redux": "3.5.2",
    "redux-thunk": "2.0.1",
    "toastr": "2.1.2"
  },
  "devDependencies": {
    "babel-cli": "6.8.0",
    "babel-core": "6.8.0",
    "babel-loader": "6.2.4",
    "babel-plugin-react-display-name": "2.0.0",
    "babel-preset-es2015": "6.6.0",
    "babel-preset-react": "6.5.0",
    "babel-preset-react-hmre": "1.1.1",
    "babel-register": "6.8.0",
    "colors": "1.1.2",
    "compression": "1.6.1",
    "cross-env": "1.0.7",
    "css-loader": "0.23.1",
    "enzyme": "2.2.0",
    "eslint": "2.9.0",
    "eslint-plugin-import": "1.6.1",
    "eslint-plugin-react": "5.0.1",
    "eslint-watch": "2.1.11",
    "eventsource-polyfill": "0.9.6",
    "expect": "1.19.0",
    "express": "4.13.4",
    "extract-text-webpack-plugin": "1.0.1",
    "file-loader": "0.8.5",
    "jsdom": "8.5.0",
    "mocha": "2.4.5",
    "nock": "8.0.0",
    "npm-run-all": "1.8.0",
    "open": "0.0.5",
    "react-addons-test-utils": "15.0.2",
    "redux-immutable-state-invariant": "1.2.3",
    "redux-mock-store": "1.0.2",
    "rimraf": "2.5.2",
    "style-loader": "0.13.1",
    "url-loader": "0.5.7",
    "webpack": "1.13.0",
    "webpack-dev-middleware": "1.6.1",
    "webpack-hot-middleware": "2.10.0"
  } 
}

step 2: setup the dev server with webpack, and for the developing tools all put it inside the tools folder.

  • in the root project create the webpack.config.dev.js, there are the standards

import webpack from 'webpack';
import path from 'path';

export default {
  debug: true,
  devtool: 'cheap-module-eval-source-map',
  noInfo: false,
  entry: [
    'eventsource-polyfill', // necessary for hot reloading with IE
    'webpack-hot-middleware/client?reload=true', //note that it reloads the page if hot module reloading fails.
    './src/index'
  ],
  target: 'web',
  output: {
    path: __dirname + '/dist', // Note: Physical files are only output by the production build task `npm run build`.
    publicPath: '/',
    filename: 'bundle.js' 
  },
  devServer: {
    contentBase: './src' //the folder put the source files
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),//for the hot load
    new webpack.NoErrorsPlugin()
  ],
  module: {
    loaders: [
      {test: /\.js$/, include: path.join(__dirname, 'src'), loaders: ['babel']},
      {test: /(\.css)$/, loaders: ['style', 'css']},
      {test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: "file"},
      {test: /\.(woff|woff2)$/, loader: "url?prefix=font/&limit=5000"},
      {test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=application/octet-stream"},
      {test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=image/svg+xml"}
    ]
  }
};

        

step 3: create a file named srcServer.js inside the tools, npm scripts already has the command will run to open the dev server.

 
import express from 'express';
import webpack from 'webpack';
import path from 'path';
import config from '../webpack.config.dev';
import open from 'open';

/* eslint-disable no-console */

const port = 3000;
const app = express();
const compiler = webpack(config);

app.use(require('webpack-dev-middleware')(compiler, {
  noInfo: true,
  publicPath: config.output.publicPath
}));

app.use(require('webpack-hot-middleware')(compiler));

app.get('*', function(req, res) {
  res.sendFile(path.join( __dirname, '../src/index.html'));
});

app.listen(port, function(err) {
  if (err) {
    console.log(err);
  } else {
    open(`http://localhost:${port}`);
  }
});

step 4: for people like to set up testing driver developer, create a testSetp.js inside the tools folder:


process.env.NODE_ENV = 'test';

require('babel-register')();

require.extensions['.css'] = function () {return null;};
require.extensions['.png'] = function () {return null;};
require.extensions['.jpg'] = function () {return null;};

var jsdom = require('jsdom').jsdom;

var exposedProperties = ['window', 'navigator', 'document'];

global.document = jsdom('');
global.window = document.defaultView;
Object.keys(document.defaultView).forEach((property) => {
  if (typeof global[property] === 'undefined') {
    exposedProperties.push(property);
    global[property] = document.defaultView[property];
  }
});

global.navigator = {
  userAgent: 'node.js'
};

documentRef = document; 

in the script I have

  "test": "mocha --reporter progress tools/testSetup.js \"src/**/*.spec.js\"",

will run with it.

step 5: setup the .babelrc in the root project

{
  "presets": ["react", "es2015"],
  "env": {
    "development": {
      "presets": ["react-hmre"]
    }
  }
}

step 6 : setup .eslintrc inside the root project


{
  "extends": [
    "eslint:recommended",
    "plugin:import/errors",
    "plugin:import/warnings"
  ],
  "plugins": [
    "react"
  ],
  "parserOptions": {
    "ecmaVersion": 6,
    "sourceType": "module",
    "ecmaFeatures": {
      "jsx": true
    }
  },
  "env": {
    "es6": true,
    "browser": true,
    "node": true,
    "jquery": true,
    "mocha": true
  },
  "rules": {
    "quotes": 0,
    "no-console": 1,
    "no-debugger": 1,
    "no-var": 1,
    "semi": [1, "always"],
    "no-trailing-spaces": 0,
    "eol-last": 0,
    "no-unused-vars": 0,
    "no-underscore-dangle": 0,
    "no-alert": 0,
    "no-lone-blocks": 0,
    "jsx-quotes": 1,
    "react/display-name": [ 1, {"ignoreTranspilerName": false }],
    "react/forbid-prop-types": [1, {"forbid": ["any"]}],
    "react/jsx-boolean-value": 1,
    "react/jsx-closing-bracket-location": 0,
    "react/jsx-curly-spacing": 1,
    "react/jsx-indent-props": 0,
    "react/jsx-key": 1,
    "react/jsx-max-props-per-line": 0,
    "react/jsx-no-bind": 1,
    "react/jsx-no-duplicate-props": 1,
    "react/jsx-no-literals": 0,
    "react/jsx-no-undef": 1,
    "react/jsx-pascal-case": 1,
    "react/jsx-sort-prop-types": 0,
    "react/jsx-sort-props": 0,
    "react/jsx-uses-react": 1,
    "react/jsx-uses-vars": 1,
    "react/no-danger": 1,
    "react/no-did-mount-set-state": 1,
    "react/no-did-update-set-state": 1,
    "react/no-direct-mutation-state": 1,
    "react/no-multi-comp": 1,
    "react/no-set-state": 0,
    "react/no-unknown-property": 1,
    "react/prefer-es6-class": 1,
    "react/prop-types": 1,
    "react/react-in-jsx-scope": 1,
    "react/require-extension": 1,
    "react/self-closing-comp": 1,
    "react/sort-comp": 1,
    "react/wrap-multilines": 1
  }
}

there are already have script command could run check the lint


 "lint": "node_modules/.bin/esw webpack.config.* src tools",

Now could start create react components
> create index.html inside the src folder

<!DOCTYPE html>
<html lang=”en”>
<head>
<title>Pluralsight Admin</title>
</head>
<body>

/bundle.js
</body>
</html>

create index.js file


/*eslint-disable import/default */
import 'babel-polyfill';
import React from 'react';
import { render } from 'react-dom';
import { Router, browserHistory } from 'react-router';
import routes from './routes';
import './styles/styles.css'; //Webpack can import CSS files too!
import '../node_modules/bootstrap/dist/css/bootstrap.min.css';


render( 
    ,
  document.getElementById('app')
);

create route.js inside the src folder


import React from 'react';
import { Route, IndexRoute } from 'react-router';
import App from './components/App';
import HomePage from './components/home/HomePage';
import AboutPage from './components/about/AboutPage';


export default (
  
    
    
  
);

create components folder inside the src, then create App.js inside it


// This component handles the App template used on every page.
import React, {PropTypes} from 'react';


class App extends React.Component {
  render() {
    return (

heading

{this.props.children}

); } } App.propTypes = { children: PropTypes.object.isRequired }; export default App;

separate pages by folder,create home, about folder

for HomePage.js


import React from 'react';
import {Link} from 'react-router';

class HomePage extends React.Component {
  render() {
    return (

React Demo

React, Redux and React Router in ES6 for ultra-responsive web apps.

Learn more

); } } export default HomePage;

for AboutPage.js


import React from 'react';

class AboutPage extends React.Component {
  render() {
    return (

About

This application uses React, Redux, React Router and a variety of other helpful libraries.

 

); } } export default AboutPage;

source code here:

https://github.com/sandywebdesigner/react_es6_starter_demo

now run npm start it will open the page in the brower, and you could start code now. have fun!

the default page will look like this:

react_starter