react + redux · react + redux. react ... element, created using jsx syntax “virtual dom” react...

Post on 22-May-2020

96 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

“Functional UI programming”React + Redux

React

› Smallest possible react application:

ReactDOM.render(

<h1>Hello, world!</h1>,

document.getElementById('root')

);

This is a React

Element, created

using JSX syntax

“Virtual DOM”

React DOM compares the element and its children to the previous one, and only applies the DOM updates necessary to bring

the DOM to the desired state.

React only updates what’s necessary

function tick() {

const element = (

<div>

<h1>Hello, world!</h1>

<h2>It is {new Date().toLocaleTimeString()}.</h2>

</div>

);

ReactDOM.render(

element,

document.getElementById('root')

);

}

setInterval(tick, 1000);

Components

› Simplest possible React component:

function Welcome(props) {

return <h1>Hello, {props.name}</h1>;

}

Properties argument,

contains application

data

Returns a React

Element

JSX

› XML-like syntax extension to JavaScript

› Requires pre-processor

• Babel (JSX, ES6)

• Typescript (TSX)

<div>

<h1>Hello, world!</h1>

<h2>It is {new Date().toLocaleTimeString()}.</h2>

</div>

Compose with components

function SplitPane(props) {

return (<div className="SplitPane">

<div className="SplitPane-left">

{props.left}

</div>

<div className="SplitPane-right">

{props.right}

</div>

</div>);

}

function App() {

return (<SplitPane

left={ <Contacts/> }

right={<Chat/> }

/>);

}

State flows downwards (callbacks to go up)function FormattedDate(props) {

return <h2>It is {props.date.toLocaleTimeString()}.</h2>;

}

class Clock extends React.Component {

constructor(props) {

super(props);

this.state = { date: new Date() };

}

render() {

return (

<div>

<h1>Hello, world!</h1>

<FormattedDate date={this.state.date} />

<button onClick={() => this.setState({date: new Date() })}>

Reset clock

</button>

</div>

);

}

}

ReactDOM.render(

<Clock />,

document.getElementById('root')

);

Clock

Formatted

Date button

date onClick()

date

Clock

Redux

Redux

Bare-bones Redux with RxJS: demo

RxJS-based middleware for Redux

Redux-Observable

Epics

const suggestOnInputChangedEpic =

(action$: ActionsObservable<Actions>,

store: MiddlewareAPI<SearchState>,

services: IServices): Rx.Observable<Actions> => {

return action$

.actionsOfType<InputChangedAction>(InputChangedActionType)

.map(a => a.payload)

.debounceTime(SuggestDelay, services.scheduler)

.distinctUntilChanged()

.map(s => suggest(s, false));

};

IServices injected into Epic

export interface IServices {

readonly search: ISearchService;

readonly scheduler: IScheduler;

}

const services = {

search: new SomeSearchService(),

scheduler: Rx.Scheduler.async // setup the default rx scheduler for

epics as the async scheduler, to be overriden in tests

};

const epicMiddleware = createEpicMiddleware(rootEpic, { dependencies:services });

Marble-testing epics with virtual timetest("suggestEpic debounces input", () => {

// Create test scheduler

const testScheduler = createTestScheduler();

// Mock services

const servicesMock = TypeMoq.Mock.ofType<IServices>();

servicesMock.setup(m => m.scheduler).returns(() => testScheduler);

const services = servicesMock.object;

// Define marble values

const inputActions = {

a: inputChanged("rr"),

b: inputChanged("rx"),

c: inputChanged("rxjs")

};

const outputActions = {

b: suggest("rx", false),

c: suggest("rxjs", false)

};

Marble-testing epics with virtual time

// Define marble diagrams

const inputMarble = "-ab---------------------c";

const outputMarble = "----------------------b---------------------c";

// Mock input actions stream

const action$ = createTestAction$FromMarbles<Actions>(testScheduler, inputMarble,

inputActions);

// Apply epic on actions observable

const outputAction$ = suggestOnInputChangedEpic(action$, store, services);

// Assert on the resulting actions observable

testScheduler.expectObservable(outputAction$).toBe(outputMarble, outputActions);

// Run test

testScheduler.flush();

});

top related