Skip to content

Latest commit

 

History

History
642 lines (475 loc) · 15.3 KB

08.1.react.md

File metadata and controls

642 lines (475 loc) · 15.3 KB

Fyrirlestur 8.1

React #1

Vefforritun 2 — HBV403G

Ólafur Sverrir Kjartansson, osk@hi.is


Sagan

  • Frá því að „Web 2.0“ var skilgreint 2004 hafa vefir verið að verða flóknari
  • jQuery og önnur DOM tengd library komu kringum 2005 og hjálpuðu við að smíða cross-browser vefi
  • Stærri „framework“ til að skrifa vefi komu fram, t.d. Dojo, ExtJs
  • Backbone.js kom í kringum 2010, library til að tengja vef og API

  • AngularJS kom einnig kringum 2010 sem framework til að búa til „single page applications“
  • Polymer byrjaði sem polyfill fyrir web components, W3C staðal sem hefur verið lengi í vinnslu og hægt og rólega fengið meiri stuðning í vöfrum
  • Ember.js ...
  • Vue.js ...
  • React ...

Single page application

  • Single page application eða SPA eru vefforrit sem, eftir fyrsta load, framkvæma aldrei „refresh“
  • Vefur hagar sér meira einsog desktop forrit
  • Fáum ný gögn frá vefþjón með Ajax eða álíka

React!


export default class Toggle extends Component {
  state = { toggled: true }

  handleClick = () => {
    this.setState(prev => ({
      toggled: !prev.toggled
    }));
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.toggled ? 'ON' : 'OFF'}
      </button>
    );
  }
}

Grunnhugmynd React

  • React byggir á því að aðskilnaður milli markup í formi template mála og lógíkar (JavaScript) sé órökréttur
    • Template mál hafa öðruvísi, ekki jafn kröftugan syntax
  • Markup og lógík eru í eðli sínu tengd saman og þessi aðskilnaður byggir á tækni

React

  • Highly cohesive
    • Hver hluti inniheldur lang flest sem þarf til birtingar og notkunar
  • Loosely coupled
    • Hver hluti er sjálfum sér nægur og þarf ekki aðra hluti

React og JavaScript

  • Mælt með að nota ES6/2015 með React
  • import og export í staðinn fyrir require og module.exports
  • babel notað til að transpile'a

Starter kits

  • Mörg, mörg, tæki og tól sem eru notuð við þróun á react verkefnum
    • webpack, react, babel, eslint, redux, stylelint, sass, postcss, o.fl.
  • Opinionated
    • Sass er best! Nei Less!
  • Unopinionated
    • Leysir grunnverkefni en tiltekur ekki ákveðin tól

Mynd af manni fyrir framan afskaplega flókið flæðirit

Marc was almost ready to implement his "hello world" React app

Thomas Fuchs (@thomasfuchs), March 12, 2016


  • Starter kit fyrir react sem er viðhaldið af react teymi
  • „Zero config“
  • Felur allar flækjur
  • Unopinionated
  • Mjög góður staður til að byrja á

create react app

  • Munum nota í okkar verkefnum
  • Margar uppskriftir til að bæta við auka tólum
  • Getum síðan „sloppið“ frá create react app með npm run eject
    • Færir öll dependency, tól og build ferli inn í project

create react app – uppsetning

> npx create-react-app my-app
> cd my-app
> npm start

create react app tól

  • Þegar við keyrum fáum við:
    • lágmarks linting
    • hot reload ✨
  • Öll verkefni munu aðeins keyra á client
    • Skoðum e.t.v. server-side rendering (SSR) ef tími gefst

  • Extension fyrir Chrome og Firefox
  • Leyfir okkur að skoða componenta, prop og state

Developer experience

  • Ein af meginreglum við þróun á React er að forritun sé unun
    • Góð skjölun
    • Góð villuskilaboð
  • Auka hlutir sem eru næs
    • Látið vita af algengnum innsláttarvillum
    • Validation á DOM tré
    • o.fl.

JSX

  • JSX er viðbót við JavaScript sem leyfir okkur að lýsa viðmóti
  • Blandar saman HTML elementum, React componentum og JavaScript
  • 😱

JSX tré

  • Myndar tré einsog DOM
    • JSX má hreiðra
  • Element sem byrja á stórum staf eru React element
  • Element sem byrja á litlum staf eru túlkuð sem DOM element
  • Öll lauf trés eru DOM element

  • Vefjum JSX yfirleitt í () til að koma í vef fyrir automatic semicolon insertion
  • Innan {} í JSX getum við sett JavaScript segðir
    • (<p>Testing {[1, 2, 3].join(', ')}</p>)
  • JSX er líka túlkað sem segð
    • return (<h1>Hello world!</h1>);

  • Element í JSX geta átt attribute
    • Skrifuð með camelCase
    • {} fyrir expression, "" fyrir strengi
    • Frístandandi attribute (án gildis) er túlkað sem true
    • class er frátekið orð í JavaScript og notum því className ❗️

  • Öll gildi sem túlkuð eru í JSX eru escaped, verndar fyrir XSS
  • Getum notað self-closing syntax úr XML/XHTML
  • (<img src={img.url} className="image" />)
  • (<MyInput required />)

JSX túlkað

  • JSX er syntactic sugar fyrir kall í React.createElement
  • Eftir þýðingu verða allar JSX segðir endurkvæmt köll í það
  • Til þess að JSX virki yfirhöfuð þarf að vera búið að importa React:
    • import React from 'react'

const element = (
  <h1 className="greeting">
    <span>Hello, world!</span>
  </h1>
);
const element = React.createElement(
  "h1",
  { className: "greeting" },
  React.createElement(
    "span",
    null,
    "Hello, world!"
  )
);

Declarative API

  • React hefur declarative API
    • Einsog HTML
  • Við segjum hvernig við viljum að UI sé og react passar uppá að það passi
  • Ólíkt imperative API þar sem við framkvæmum skref-fyrir-skref það sem þarf til að UI sé rétt

React element og DOM

  • Þar sem JSX element eru ekki DOM element er töluvert ódýrara að búa þau til
    • Þar til að á einhverjum tímapunkti sem við búum til DOM element í raun
  • Til að búa til DOM tré köllum við í fall frá ReactDOM og gefum rót trés ásamt DOM nóðu sem mun innihalda niðurstöðu, oft nóða með id root
    • ReactDOM.render(element, document.getElementById('root'));

Uppfærsla í DOM

  • Ef eitthvað lætur element breytast, eða ef við köllum aftur í render mun React aðeins uppfæra það sem breyttist
  • React heldur utan um „virtual DOM“ (VDOM) sem er staða á UI geymd í minni sem er síðan syncuð við alvöru DOM

  • Útgáfa 16 af react breytir útfærslu úr því að vera sync í að vera async (kallað „Fiber“)
  • Uppfærsla mun eiga sér stað ef kallað er aftur í render eða ef á einhverjum tímapunkti, í einhverju component er kallað á setState en það mun uppfæra hluttré frá þeim component

Reconciliation

  • „Diff“ sem er keyrt á vdom og dom og uppfærir aðeins það sem þarf að breyta til að láta passa
  • Bestu reiknirit til að breyta einu tré í annað kosta í kringum O(n³) svo React þarf að stytta sér leið
    • Öllu hluttré er hent ef foreldri breytist
    • Fyrir lista af hlutum ætti forritari að láta vita hvort breytingar hafi átt sér stað með key attribute, gefum lista stable id

Reconciliation reiknirit

  1. React býr til nýtt VDOM
  2. diffar við gamla
  3. Útbýr minnsta sett af DOM aðgerðum til að breyta á milli
  4. Framkvæmir aðgerðir

Components

  • Með því að nota components getum við skipt viðmótinu okkar upp í sjálfstæðar einingar
    • Mjög góð pæling sem virkar afskaplega vel í praxís
  • Getum hugsað um component einsog JavaScript fall: tekur við props (properties) sem hlut með gögnum og skilar React element(s)

  • Hægt að skilgreina með function, þá kallað functional component, sem skilar elements með return
  • Eða class, skilar elements í gegnum return á render() falli
  • Ef við notum React element í JSX eru attribute send inn sem prop
    • Þegar element tekur mörg attribute er gott að setja hvert og eitt í sér línu

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

const element = <Welcome name="Sara" />;
<h1>Hello, Sara</h1>

(
  <Welcome title="Velkomin" subtitle="Gaman" color="green" size="large" />
)
// vs.
(
  <Welcome
    title="Velkomin"
    subtitle="Gaman"
    color="green"
    size="large"
  />
)

Skilagildi componenta

  • Component geta skilað:
    • Elements, JSX segð
    • Fylki af elements, JSX segðum
    • falsy gildi – ekkert verður skrifað í DOM

function FooBar(props) {
  return [
    <p>foo</p>,
    <p>bar</p>,
  ];
}

Fylki í componentum

  • Við getum unnið með fylki í componentum og ítrað út gildum þeirra í element
  • React mun kvarta yfir því að það vanti key
    • Flýtileið fyrir React til að rendera hraðar
  • Ættum að setja sem sannanlega einstakt gildi
    • Ef við getum ekki er hægt að nota index fylkis

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
  <li key={number.toString()}>
    {number}
  </li>
)

Fragments

  • Stundum viljum við skila mörgum elementum
  • Getum skilað fragment sem útbýr ekki element
    • <React.Fragment>foo</React.Fragment>
  • Ef við skilum fragment í ítrun verðum við að skilgreina key

function Table(props) {
  return (
    <table>
      <tr>
        <Columns />
      </tr>
    </table>
  );
}

function Columns(props) {
  return (
    <React.Fragment>
      <td>Foo</td>
      <td>Bar</td>
    </React.Fragment>
  );
}

Component

  • Ekkert sem stoppar okkur í því að nota sama component aftur og aftur
  • Afskaplega handhægt og eykur endurnýtingu
  • Component getur innihaldið component sem inniheldur component sem ... o.s.fr.

  • Ættum að skipta UI upp í fleiri, minni components
    • Algeng mistök í byrjun er að skrifa of stór component
  • Ef orðið flókið – búa til nýtt component

App component

  • Algengt pattern er að hafa eitt App „yfir“ component sem rót fyrir UI
    • Tekur ekki inn nein props
  • Stillir og setur upp hluti og sér um routing

function App() {
  return (
    <main>
      <Welcome name="world" />
      <Welcome name="foo" />
    </main>
  );
}

Conditional Rendering

  • Stundum viljum við stýra því hvað er renderað eftir því í hvaða stöðu component er
  • Getum:
    • Notað flæðistýringar í render
    • Geymt element í breytu
    • Notað && (útaf short-circuiting)
    • Notað ternary virkjan ? :

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) {
    return <UserGreeting />;
  }
  return <GuestGreeting />;
}

class Login extends React.Component {
  render() {
    if (this.props.isLoggedIn) {
      button = <LogoutButton />;
    } else {
      button = <LoginButton />;
    }

    return (
      <div>
        <Greeting isLoggedIn={isLoggedIn} />
        {button}
      </div>
    )
  }
}

function Mailbox(props) {
  const unreadMessages = props.unreadMessages;
  return (
    <div>
      <h1>Hello!</h1>
      {unreadMessages.length > 0 &&
        <h2>
          {unreadMessages.length} unread messages.
        </h2>
      }
    </div>
  );
}

function LoggedIn(props) {
  const isLoggedIn = props.isLoggedIn;
  return (
    <div>
      The user is
      <b>{isLoggedIn ? 'currently' : 'not'}</b>
      logged in.
    </div>
  );
}

Props

  • React components ættu að vera hrein föll m.t.t. props
    • Aldrei breyta props, þau eru read-only
  • Þegar við bregðumst við breytingum í UI notum við state
  • children er sérstakt prop sem inniheldur börn elements, ef einhver

children

  • children geta verið sett sem mismunandi gagnatög
    • undefined ef engin börn
    • string ef texti
    • object ef eitt barn sem er element
    • array ef fleiri en eitt barn sem er element

Getur verið bras að athuga týpu en React bíður upp á React.Children hjálparföll

function Childrens(props) {
  const { children } = props;
  const childrenAsArray =
    React.Children.toArray(children);

  return (
    <div>
      <p>{React.Children.count(children)} börn</p>
      {React.Children
        .map(children, child => child)
      }
    </div>
  );
}

propTypes

  • Eftir því sem við skrifum fleiri components og setjum þau saman aukast líkur á böggum
  • React hefur stuðning við prop-types sem keyrir type check á runtime í þróun
  • Skilgreinum sem propTypes hlut á function eða class
    • Hver lykill í hlut á við eitt prop, gildi lykils er gerð sem prop ætti að vera

  • Mikið af mismumandi týpum og aðferðum til að skilgreina
  • Ef við endum á isRequired mun React senda viðvörun ef gildi er ekki sent inn í component
  • Notum helst
    • node, hvað sem hægt er að birta
    • JavaScript týpur: array, bool, func, number, object
    • Listar af hlutum, oneOf og oneOfType, arrayOf
    • Hlutur af ákveðnu formi, shape({}) þar sem hlutur er propTypes hlutur
    • o.fl.

import PropTypes from 'prop-types';

Comp.propTypes = {
  title: PropTypes.isRequired,
  type: PropTypes.oneOf(['foo', 'bar']),
  user: PropTypes.shape({
    name: PropTypes.string,
    age: PropTypes.number,
  }),
  onClick: PropTypes.func,
}

defaultProps

  • Ásamt propTypes getum við skilgreint sjálfgefin gildi með defaultProps
  • Getum þ.a. passað upp á að fá alltaf einhver gildi í props
    • Type check er keyrt eftir að defaultProp eru sett
  • Ættum ekki að skilgreina ef við notum isRequired

Comp.defaultProps = {
  type: 'foo',
  user: null,
  onClick: () => {},
}

propTypes og defaultProps á class

Ef við höfum rétta stillingar á babel (t.d. transform-class-properties) getum við sett propTypes og defaultProps sem static breytur á class

class Person extends Component {
  static propTypes = {
    name: PropTypes.string,
  }

  static defaultProps = {
    name: 'NN',
  }
  //...
}

Nánar