React

Posted by Shi

Properties

PropTypes

Json

static propTypes = {
  link: React.PropTypes.shape({
    description: React.PropTypes.string.isRequired,
    url: React.PropTypes.string.isRequired,
    id: React.PropTypes.string.isRequired,
  }),
};

Array

static propTypes = {
  links: React.PropTypes.arrayOf(React.PropTypes.shape({
    description: React.PropTypes.string.isRequired,
    url: React.PropTypes.string.isRequired,
    id: React.PropTypes.string.isRequired,
  })),
};

Handle Click

onDoorListRowClick(cell, row, rowIndex) {
  console.log('clicked', cell, row, rowIndex);
}

// OR

onDoorListRowClick=(cell, row, rowIndex) => {
  console.log('clicked', cell, row, rowIndex);
}


renderButton() {
  const { onLoginEmail } = this.props;

  return (
    <label htmlFor="LoginButton">
      <Button
        onClick={()=>this.onDoorListRowClick(1,2,3)}
      >
        Login button
      </Button>
    </label>
  );
}

react-bootstrap-table

Search

const options = {
  clearSearch: true
};

export default class SearchClearTable extends React.Component {
  render() {
    return (
      <BootstrapTable data={ products } search={ true } options={ options }>
          <TableHeaderColumn dataField='id' isKey>Product ID</TableHeaderColumn>
          <TableHeaderColumn dataField='name'>Product Name</TableHeaderColumn>
          <TableHeaderColumn dataField='price'>Product Price</TableHeaderColumn>
      </BootstrapTable>
    );
  }
}

Action

http://allenfang.github.io/react-bootstrap-table/example.html#manipulation

class ExportCSVTable extends React.Component {
  render() {
    return (
      <BootstrapTable data={ products } exportCSV={ true }>
          <TableHeaderColumn dataField='id' isKey hidden export>Product ID</TableHeaderColumn>
          <TableHeaderColumn dataField='name'>Product Name</TableHeaderColumn>
          <TableHeaderColumn dataField='price'>Product Price</TableHeaderColumn>
          <TableHeaderColumn dataField='action' export={ false }>Action</TableHeaderColumn>
      </BootstrapTable>
    );
  }
}

Export

https://github.com/AllenFang/react-bootstrap-table/blob/3ce59bf44b50aecd49fc27a2b73d4b7b23e5157c/examples/js/custom/csv-button/custom-csv-or-tsv-button.js

class ExportCSVTable extends React.Component {
  render() {
    return (
      <BootstrapTable data={ products } exportCSV={ true }>
          <TableHeaderColumn dataField='id' isKey hidden export>Product ID</TableHeaderColumn>
          <TableHeaderColumn dataField='name'>Product Name</TableHeaderColumn>
          <TableHeaderColumn dataField='price'>Product Price</TableHeaderColumn>
          <TableHeaderColumn dataField='action' export={ false }>Action</TableHeaderColumn>
      </BootstrapTable>
    );
  }
}

Hover, Striped, Condensed Table

striped class adds zebra-stripes to a table

hover class adds a hover effect (grey background color) on table rows

condensed class makes a table more compact by cutting cell padding in half

class HoverStripedTable extends React.Component {
  render() {
    return (
      <BootstrapTable data={ products } striped hover condensed>
          <TableHeaderColumn dataField='id' isKey>Product ID</TableHeaderColumn>
          <TableHeaderColumn dataField='name'>Product Name</TableHeaderColumn>
          <TableHeaderColumn dataField='price'>Product Price</TableHeaderColumn>
      </BootstrapTable>
    );
  }
}

Large Table

class LargeColumnTable extends React.Component {
  render() {
    return (
      <BootstrapTable data={ products }>
          <TableHeaderColumn width='150' dataField='id' isKey>ProductID</TableHeaderColumn>
          <TableHeaderColumn width='150' dataField='name'>ProductName</TableHeaderColumn>
          <TableHeaderColumn width='150' dataField='price'>ProductPrice</TableHeaderColumn>
          <TableHeaderColumn width='150' dataField='name'>ProductName</TableHeaderColumn>
          <TableHeaderColumn width='150' dataField='price'>ProductPrice</TableHeaderColumn>
          <TableHeaderColumn width='150' dataField='name'>ProductName</TableHeaderColumn>
          <TableHeaderColumn width='150' dataField='price'>ProductPrice</TableHeaderColumn>
          <TableHeaderColumn width='150' dataField='name'>ProductName</TableHeaderColumn>
          <TableHeaderColumn width='150' dataField='price'>ProductPrice</TableHeaderColumn>
          <TableHeaderColumn width='150' dataField='name'>ProductName</TableHeaderColumn>
          <TableHeaderColumn width='150' dataField='price'>ProductPrice</TableHeaderColumn>
          <TableHeaderColumn width='150' dataField='name'>ProductName</TableHeaderColumn>
      </BootstrapTable>
    );
  }
}

Scroll Table

class ScrollTable extends React.Component {
  render() {
    return (
      <BootstrapTable data={ products } height='120' scrollTop={ 'Bottom' }> <!-- Available value is Top, Bottom or any number value -->
          <TableHeaderColumn dataField='id' isKey>Product ID</TableHeaderColumn>
          <TableHeaderColumn dataField='name'>Product Name</TableHeaderColumn>
          <TableHeaderColumn dataField='price'>Product Price</TableHeaderColumn>
      </BootstrapTable>
    );
  }
}

Sort

class DefaultSortTable extends React.Component {
  constructor(props) {
    super(props);

    this.options = {
      defaultSortName: 'name',  // default sort column name
      defaultSortOrder: 'desc'  // default sort order
    };
  }

  render() {
    return (
      <div>
        <BootstrapTable data={ products } options={ this.options } multiColumnSort={ 2 }>
          <TableHeaderColumn dataField='id' isKey dataSort>Product ID</TableHeaderColumn>
          <TableHeaderColumn dataField='name' dataSort>Product Name</TableHeaderColumn>
          <TableHeaderColumn dataField='price'>Product Price</TableHeaderColumn>
        </BootstrapTable>
      </div>
    );
  }
}

react-router

https://css-tricks.com/react-router-4/

react-router API

https://reacttraining.com/react-router/web/api

Auth

https://themeteorchef.com/tutorials/getting-started-with-react-router-v4

<BrowserRouter> should be used when you have a server that will handle dynamic requests (knows how to respond to any possible URI).

<HashRouter> should be used for static websites (can only respond to requests for files that it knows about).

<Route>

<Route> component is the main building block of React Router. Anywhere that you want to only render something if it matches the location’s pathname, you should create a <Route> element.

<Route> expects a path prop string that describes the type of pathname that the route matches — for example, <Route path='/roster'/> should match a pathname that begins with /roster

we strategically place the routes for/users/add before /users to ensure the correct matching. Since the path /users/add would match for /users and /users/add, putting the /users/add first is best.

match.path vs match.url

match.url would be "/users/5". Useful for building nested s

match.path would be "/users/:userId". **Useful for building nested s**

<NavLink> works the same as <Link> but gives you some extra styling abilities depending on if the <NavLink> matches the browser’s URL.

Image uploader

https://codepen.io/hartzis/pen/VvNGZP

https://github.com/baaraak/react-images-upload

https://gist.github.com/hartzis/0b77920380736f98e4f9

https://github.com/FineUploader/react-fine-uploader

https://css-tricks.com/image-upload-manipulation-react/

http://www.hartzis.me/react-image-upload/

https://medium.com/ecmastack/uploading-files-with-react-js-and-node-js-e7e6b707f4ef

https://juejin.im/entry/57b923225bbb50005b794943

http://jafeney.com/2016/08/11/2016-08-11-upload/

https://github.com/Jafeney/Royal

https://www.jianshu.com/p/e9ce78270860

http://react-component.github.io/upload/

Tools

Redux DevTools

Check installed NPM package version npm list --depth=0

Yarn

npm install -g yarn

Webstorm Set indent to 2 space

File name: .editorconfig

# editorconfig.org
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false

Webpack

webpack is a module bundler. This means webpack takes modules with dependencies and emits static assets representing those modules.

Configuration file is: webpack.config.dev.js

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

export default {
  debug: true,
  devtool: 'cheap-module-eval-source-map',
  noInfo: false, //Prod: set to true
  entry: [
    'eventsource-polyfill', // necessary for hot reloading with IE
    'webpack-hot-middleware/client?reload=true', //For hot reload. Note that it reloads the page if hot module reloading fails.
    './src/index'
  ],
  target: 'web',
  output: { //Webpack do not generate any code, but we should put it here
    path: __dirname + '/dist', // Note: Physical files are only output by the production build task `npm run build`.
    publicPath: '/',
    filename: 'bundle.js'
  },
  devServer: {
    contentBase: './src'
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(), //Hot replace module 
    new webpack.NoErrorsPlugin()
  ],
  module: { // Tell webpack the type of files we handle
    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'}
    ]
  }
};

Debug

Webstorm debug setting

For ‘React-boilerplate’

  1. Install JetBrain Chrome Extension
  2. Change WebPack devtool config to source-map (This line)
  3. Run web server (npm run start)
  4. Create Run Configuration (Run > Edit Configurations) : Add new JavaScript Debug
    1. URL: http://localhost:3000
    2. Map your root directory (Remote URLs of local files) with webpack://.
  5. ​Right click JetBrain plugin icon, click “Inspect In WebStorm”

Error Handling

Pay attention to imported action and selectors

If React can not find the action or selectors, it will give you some useless information to confuse you. Like this:

uncaught at githubData 

 at takeLatestHelper 

 at getSupportDataSaga 

 TypeError: Object(...) is not a function
at getSupportDataSaga$ (http://localhost:3000/2.4e77eae8f36a2ed5cbf2.hot-update.js:145:139)
at tryCatch (webpack:///./node_modules/regenerator-runtime/runtime.js?:65:40)
at Generator.invoke [as _invoke] (webpack:///./node_modules/regenerator-runtime/runtime.js?:303:22)
at Generator.prototype.(anonymous function) [as next] (webpack:///./node_modules/regenerator-runtime/runtime.js?:117:21)
at next (webpack:///./node_modules/redux-saga/es/internal/proc.js?:311:27)
at currCb (webpack:///./node_modules/redux-saga/es/internal/proc.js?:387:7)
at runSelectEffect (webpack:///./node_modules/redux-saga/es/internal/proc.js?:690:7)
at runEffect (webpack:///./node_modules/redux-saga/es/internal/proc.js?:433:1124)
at next (webpack:///./node_modules/redux-saga/es/internal/proc.js?:315:9)
at proc (webpack:///./node_modules/redux-saga/es/internal/proc.js?:270:3) # Lib

material-ui https://github.com/mui-org/material-ui

Redux-saga 中文文档

Text input local state example https://openclassrooms.com/courses/build-web-apps-with-reactjs/handle-user-input

https://codepen.io/gaearon/pen/wgedvV?editors=0010

react-widgetshttps://github.com/jquense/react-widgets

Note

React Template

https://thefront.maccarianagency.com/

React Skeleton

react-boilerplate

react-starter-kit

Official Tutorial

Pluralsight-redux-starter React-slingshot

React boilerplate by Facebook

Starter tutorial

http://chenglou.github.io/react/docs/reusable-components.html#mixins

https://teropa.info/blog/2015/09/10/full-stack-redux-tutorial.html

https://www.sitepoint.com/how-to-build-a-todo-app-using-react-redux-and-immutable-js/

great redux course: https://egghead.io/courses/getting-started-with-redux

https://www.fullstackreact.com/articles/react-tutorial-cloning-yelp/

test case on angular