react quiz live

Jared Anderson

Mike Jasper

ICS Stack Team

what we're building...

realtime polling app

2 "page"

Lorem Ipsum?

Mollit nulla deserunt?

Laborum in reprehenderit?

Lorem Ipsum?

Minim Lorem culpa​?

Home - Question List

"page" 1

Answer 1 

Answer 2

Answer 3

5

3

2

Lorem Ipsum?

Answer 1 

Answer 2

Answer 3

Question

"page" 2

Specs

  • my vote changes bar chart real-time
  • others' votes change bar chart real-time

app

architecture

App

API

rest & socket.io

render in browser

render on server

high level

App

API

rest endpoints

db

local app state

UI components

socket endpoints

service clients

JSON

API

App

tools & tech

app

  • node / browser
  • react
  • redux
  • redux-thunk
  • react-router
  • socket.io
  • helper utils

api

  • node
  • express.js
  • rethinkdb (client)
  • socket.io

data contracts

between app and api

[
    {
        "id": "5694c574-0348-45dd-bde0-2e05563712fe",
        "question": "What's your favorite America?"
    },
    {
        "id": "5e0ca5e0-d31c-418f-a4eb-79747d03d6fd",
        "question": "Where should we go to lunch?"
    },
    {
        "id": "6fed2bae-4325-4e2b-8c93-0662d8dcd682",
        "question": "Would you like fries with that?"
    },
    {
        "id": "2c703db8-3912-4690-a553-5dfb59269a6d",
        "question": "Who would win in a fight?"
    }
]

GET /v1/questions/list

{
    "id": "5e0ca5e0-d31c-418f-a4eb-79747d03d6fd",
    "options": [
        {
            "id": 0,
            "responses": 0,
            "text": "Cubbies"
        },
        {
            "id": 1,
            "responses": 0,
            "text": "Lonestar"
        },
        {
            "id": 2,
            "responses": 0,
            "text": "J & C"
        },
        {
            "id": 3,
            "responses": 0,
            "text": "SmashBurger"
        },
        {
            "id": 4,
            "responses": 1,
            "text": "The Pie"
        }
    ],
    "question": "Where should we go to lunch?"
}

GET /v1/questions/:id

[
    {
        "option": 1,
        "question": "6fed2bae-4325-4e2b-8c93-0662d8dcd682",
        "user": "14289a42-13fc-452c-9c72-328b75c6b1b3"
    }
]

GET /v1/answers/user/:id

{
    "user": "bcdf879d-6fc1-4186-8062-85ca42c8cc93",
    "option": 0
}

POST /v1/questions/:id/answers

{
    "type": "delete",
    "data": {
        "id": "74d6f9c2-44d9-4146-aa40-000d08e06a82",
        "option": 4,
        "question": "5e0ca5e0-d31c-418f-a4eb-79747d03d6fd",
        "user": "c23c8b9e-fd52-490b-a940-4c7bef2e7ac8"
    }
}

ws /

event name: "answers.change"

{
    "type": "create",
    "data": {
        "id": "49100db7-d5f6-4568-8e71-756494338459",
        "option": 3,
        "question": "5e0ca5e0-d31c-418f-a4eb-79747d03d6fd",
        "user": "c23c8b9e-fd52-490b-a940-4c7bef2e7ac8"
    }
}

react

components

App

API

rest endpoints

db

local app state

UI components

socket endpoints

service clients

JSON

You Are Here

UI components

=

let's build this

Answer 1 

Answer 2

Answer 3

5

3

2

Lorem Ipsum?

Answer 1 

Answer 2

Answer 3

Question

"page" 2

Answer 1 

Answer 2

Answer 3

5

3

2

make this bar chart

live code

the <BarChart/> component

the other components

code review

Usage Examples

<HomeLayout
    questions={[
        {
            text: "Quis ut amet excepteur exercitation incididunt ?",
            href: "#123",
            size: 1
        },
        {
            text: "Aute aliquip proident sunt ipsum reprehenderit elit?",
            href: "#123",
            size: 3
        },
        {
            text: "Nisi consectetur ex magna id?",
            href: "#123",
            size: 2
        }
    ]}
/>
<QuestionLayout
    id={1234}
    text="Pick a number between 1 and 4?"
    name="test"
    options={[
        { id: 1, value: 1, label: "One", qty: 7 },
        { id: 2, value: 2, label: "Two", qty: 5 },
        { id: 3, value: 3, label: "Three", qty: 2 },
        { id: 4, value: 4, label: "Four", qty: 6 }
    ]}

    onVote={action("Changed")}
/>

api

App

API

rest endpoints

db

local app state

UI components

socket endpoints

service clients

JSON

You Are Here

db overview

Data Explorer

Show Tables

CRUD example

Show `.update()` functionality

show our data models

API: /src/libs/models/db.js

code review

live code

src/routes/questions.js

GET /v1/questions/list

api

live code

src/routes/questions.js

GET /v1/questions/:id

api

code review

src/routes/questions.js

POST /v1/questions/:id

api

API: /src/routes/answers.js

code review

code review

API: /src/server.js

inspect endpoints

app

data retrieval

App

API

rest endpoints

db

local app state

UI components

socket endpoints

service clients

JSON

You Are Here

code review

src/app/services/

jump to 06-services

review

templates/

redux

a predictable state container for JavaScript apps

App

API

rest endpoints

db

local app state

UI components

socket endpoints

service clients

JSON

You Are Here

redux

single source of truth

state is read-only

derived new state

const {questions} = store.getState()
(state=0, {type}) => {
    switch (type) {
        case INCREMENT:
            return state+1;
        default:
            return state
    }

change requests dispatched 

store.dispatch({type: INCREMENT})

subscribe to changes

store.subscribe( () => 
    store.getState()
)
questions.addAnswer(1);

Redux?!

Redux offers a tradeoff. It asks you to:

  • describe application state as plain objects and arrays.
  • describe changes in the system as plain objects.
  • describe the logic for handling changes as pure functions.

In return:

  • predictability
  • decoupled architecture
  • scalability
  • change resilient
  • clarity
  • maintainability
  • shareable data
  • LOTS more

potentially more boilerplate & indirection, but generally worth it :)

Redux Lingo

  • Actions: plain objects that describe the desired change of state
  • Action Creators: helper functions that create actions
  • Reducers: functions that accept current state & action objects and returns new state
  • Selectors: helper function for selecting pieces of data from the store 

our app's data store:

data our app needs

  • question summaries
  • question details
  • answer stats
  • my own answers
  • my user info

action types

RECEIVE_MY_ANSWERS RECEIVE_ANSWER_TALLY RECEIVE_ANSWER_INCREMENT RECEIVE_ANSWER_DECREMENT

 

RECEIVE_QUESTION_SUMMARY RECEIVE_FULL_QUESTION

 

RECEIVE_USER_PROFILE

(events) that change our app state

code review

src/app/store/constants.js

jump to 07-store-constants

action types

live code

src/app/store/reducers/questions.js

src/app/store/index.js

a reducer

redux dev tools

demo

{
    type: 'RECEIVE_QUESTION_SUMMARY',
    payload: {
        id: 1234,
        question: "Where should we go to lunch?"
    }
}

live code

src/app/store/actions/questions.js (part 1)

an action-creator

code review

src/app/store/reducers/user-profile.js

src/app/store/reducers/answers.js

src/app/store/index.js

11-actions-almost-finish

more reducers

code review

src/app/store/actions/user-profile.js

src/app/store/actions/answers.js

more actions

live code

src/app/containers/app.js

a "container"

code review

src/app/containers/home.js

another "container"

13-home-container

code review

src/app/store/actions/questions.js*

src/app/containers/app.js*

src/app/containers/question.js

src/app/routes.js*

final product

app demo

if internet, go to:

http://10.228.251.173:8888

Video

if things went badly...

React Quiz Live

By Jared Anderson

React Quiz Live

  • 1,421