Skip to content

Latest commit

 

History

History
567 lines (427 loc) · 9.06 KB

s2.md

File metadata and controls

567 lines (427 loc) · 9.06 KB

REACT BASICS


## Burak Kırkıl __*Frontend Developer, VNGRS*__

Seperation of Concern

HTML (Structure)

CSS (Style)

Javascript (Behaviour)


foo
├── foo.tmpl.html
├── foo.css
└── foo.js

bar
├── bar.tmpl.html
├── bar.css
└── bar.js


only structure?

<div
  id="jsFooController"
  class="fancy-div"
  data-id="458">

  Lorem ipsum dolor sit amet.

</div>

MV* Frameworks


todomvc


knockoutjs

<div>You've clicked <span data-bind='text: numberOfClicks'>&nbsp;</span> times</div>
<button data-bind='click: registerClick, disable: hasClickedTooManyTimes'>
  Click me
</button>
<div data-bind='visible: hasClickedTooManyTimes'>
  That's too many clicks! Please stop before you wear out your fingers.
  <button data-bind='click: resetClicks'>Reset clicks</button>
</div>
var ClickCounterViewModel = function() {
  this.numberOfClicks = ko.observable(0);

  this.registerClick = function() {
    this.numberOfClicks(this.numberOfClicks() + 1);
  };

  this.resetClicks = function() {
    this.numberOfClicks(0);
  };

  this.hasClickedTooManyTimes = ko.pureComputed(function() {
    return this.numberOfClicks() >= 3;
  }, this);
};

ko.applyBindings(new ClickCounterViewModel());

angular

<!-- heroes.component.html -->
<li *ngFor="let hero of heroes" (click)="onSelect(hero)">
// heroes.component.ts
@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css']
})
/* heroes.component.css */
.heroes li {
  background-color: #EEE;
  margin: .5em;
  padding: .3em 0;
}

mustache

<ul>
  {{#musketeers}}
    <li>{{.}}</li>
  {{/musketeers}}
</ul>
var data = {
  "musketeers": ["Athos", "Aramis", "Porthos", "D'Artagnan"]
};

function loadUser() {
  $.get('template.mst', function(template) {
    var rendered = Mustache.render(template, data);
    $('#target').html(rendered);
  });
}

app(state) => view


frontend applications

app(state) => view_t0

sideEffect > app(updatedState) => view_t1

anotherSideEffect > app(updatedState) => view_t2

...


?


javascript


composition over inheritance

f( g() ) => view

demo


Virtual DOM


Virtual DOM is the representation of DOM as an object. When changes to state of application are made, new Virtual DOM is compared(applying diffing algorithms) with DOM and only changes are reflected, not causing full re-rendering of DOM.


html like...

<div id="foo">Hello world</div>
someTemplateFunc("div", {id: "foo"}, "Hello world");

hyperscript

var h = require('hyperscript')

h('div#page',
  h('div#header',
    h('h1.classy', 'h', { style: {'background-color': '#22f'} })),
  h('div#menu', { style: {'background-color': '#2f2'} },
    h('ul',
      h('li', 'one'),
      h('li', 'two'),
      h('li', 'three'))),
    h('h2', 'content title',  { style: {'background-color': '#f22'} }),
    h('p',
      "so it's just like a templating engine,\n",
      "but easy to use inline with javascript\n"),
    h('p',
      "the intention is for this to be used to create\n",
      "reusable, interactive html widgets. "))

https://github.com/hyperhype/hyperscript


.jsx


@babel/plugin-transform-react-jsx

// .jsx syntax
var profile =
  <div>
    <img src="avatar.png" className="profile" />
    <h3>{[user.firstName, user.lastName].join(' ')}</h3>
  </div>
// output
var profile =
  React.createElement("div", null,
    React.createElement("img",
      { src: "avatar.png", className: "profile" }
    ),
    React.createElement("h3", null,
      [user.firstName, user.lastName].join(" ")
    )
  )

<html>
...

<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

<script type="text/babel">
  // .jsx syntax
  var profile =
    <div>
      <img src="avatar.png" className="profile" />
      <h3>{[user.firstName, user.lastName].join(' ')}</h3>
    </div>
</script>

...
</html>

React + ReactDOM = HTML

React + 📱 = ReactNative

React + WebVR = React 360


React


$ npm init
$ npm install react react-dom
$ npm install -D @babel/core @babel/preset-env @babel/preset-react
$ npm install -D webpack webpack-cli webpack-dev-server babel-loader

.babelrc

{
  "presets": [
    "@babel/preset-env",
    "@babel/preset-react"
  ]
}

webpack.config.js

const webpack = require('webpack')

module.exports = {
  entry: './src/index.js',
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: ['babel-loader'],
      },
    ],
  },
  resolve: {
    extensions: ['*', '.js', '.jsx'],
  },
  output: {
    path: __dirname + '/dist',
    publicPath: '/',
    filename: 'bundle.js',
  },
  devServer: {
    contentBase: './dist',
  },
}

package.json

{
  "name": "minimal-react-app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "webpack-dev-server --mode development"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "react": "^16.8.6",
    "react-dom": "^16.8.6"
  },
  "devDependencies": {
    "@babel/core": "^7.4.0",
    "@babel/preset-env": "^7.4.2",
    "@babel/preset-react": "^7.0.0",
    "babel-loader": "^8.0.5",
    "webpack": "^4.29.6",
    "webpack-cli": "^3.3.0",
    "webpack-dev-server": "^3.2.1"
  }
}

demo


  • Virtual DOM is faster than a conventional full refresh model (refreshing pages partially);
  • Mild learning curve, doesn’t require learning multiple specific concepts;
  • Reusable code components;
  • Good SEO when used together with a server-side renderer;
  • A stable working code due to one-directional data;
  • Easy debugging;
  • Easy HTML decomposition into independent and reusable pieces of code;
  • Easy testing with JEST.

components

  • Functional Components
  • Class Components

Functional Component

const App = () => {
  return (
    <h1>Hello World</h1>
  )
}

Class Component

class App extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      header: 'Hello World'
    }
  }

  render() {
    return (
      <h1>{this.state.header}</h1>
    )
  }
}

class Timer extends React.Component {
  constructor(props) {
    super(props);
    this.state = { seconds: 0 };
  }

  tick() {
    this.setState(state => ({
      seconds: state.seconds + 1
    }));
  }

  componentDidMount() {
    this.interval = setInterval(() => this.tick(), 1000);
  }

  componentWillUnmount() {
    clearInterval(this.interval);
  }

  render() {
    return (
      <div>
        Seconds: {this.state.seconds}
      </div>
    );
  }
}

ReactDOM.render( <Timer />,
  document.getElementById('timer-example')
);

### Instance Properties

  • props
  • state

### Instance Methods

  • setState
  • forceUpdate

Lifecycle Methods

  • constructor
  • componentDidMount
  • shouldComponentUpdate
  • static getDerivedStateFromProps()
  • getSnapshotBeforeUpdate()
  • componentDidUpdate
  • componentWillUnmount
  • static getDerivedStateFromError(error)
  • render

Class Properties

  • defaultProps
  • displayName

Do Not Modify State Directly

// Wrong
this.state.comment = 'Hello';
// Correct
this.setState({comment: 'Hello'});

State Updates May Be Asynchronous

For example, this code may fail to update the counter:

// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});
// Correct
this.setState((state, props) => ({
  counter: state.counter + props.increment
}));

### Teşekkürler