Skip to content

Commit

Permalink
Added episode 8
Browse files Browse the repository at this point in the history
  • Loading branch information
cassiozen committed Dec 19, 2016
1 parent 713c32a commit 0103151
Show file tree
Hide file tree
Showing 26 changed files with 5,812 additions and 0 deletions.
34 changes: 34 additions & 0 deletions episode8/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Selectors in Redux

ReactCasts, episode 8.

Selectors are neither something you import from Redux nor an external library you must install. But they are present in many Redux projects nonetheless.
Technically selectors are just convenient functions used for looking up and retrieving snippets of data from the Redux store, into your components... But they play an important role as they help cope with derived and related data - allowing Redux to store the minimal possible state.


Screencast video:
https://youtu.be/frT3to2ACCw

# Outline

- Brief introduction to Selectors.
- Sample application highlight
- Example 1: Using Selectors for computing Derived Data
- Example 2: Making selectors more practical by centralizing them all on the index reducer file.
- Example 3: Using Selectors for retrieving relational data
- Memoization and Reselect


# Build & Run Instructions

1. To build and run the code in this directory, ensure you have [npm](https://www.npmjs.com) installed

2. Install
```
npm install
```

3. Start the application
```
npm start
```
22 changes: 22 additions & 0 deletions episode8/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "hotel",
"version": "0.1.0",
"private": true,
"devDependencies": {
"react-scripts": "0.8.3"
},
"dependencies": {
"react": "^15.4.1",
"react-dom": "^15.4.1",
"react-redux": "^4.4.6",
"redux": "^3.6.0",
"redux-thunk": "^2.1.0",
"reselect": "^2.5.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
Binary file added episode8/public/fakeserver_images/deluxe-city.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added episode8/public/fakeserver_images/grandlux.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added episode8/public/fakeserver_images/royal.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added episode8/public/favicon.ico
Binary file not shown.
32 changes: 32 additions & 0 deletions episode8/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<link href="https://fonts.googleapis.com/css?family=Cormorant+Infant:300,400,500,600,700" rel="stylesheet">
<!--
Notice the use of %PUBLIC_URL% in the tag above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start`.
To create a production bundle, use `npm run build`.
-->
</body>
</html>
11 changes: 11 additions & 0 deletions episode8/src/App.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.App {
display: flex;
height: 100%;
}

.main {
height: 100%;
width: 50%;
padding: 20px 120px 20px 20px;
text-align: right;
}
50 changes: 50 additions & 0 deletions episode8/src/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import SlideShow from './components/SlideShow';
import { login } from './actions/auth';
import { fetchRooms } from './actions/rooms';
import { selectUserName, selectUserRoom } from './reducers';
import logo from './logo.png';
import './App.css';

class App extends Component {
componentDidMount() {
const { login, fetchRooms } = this.props;
login();
fetchRooms();
}

render() {
const { isFetching, userName, accomodation } = this.props;
if (isFetching || isFetching === undefined) return <div className="loader" />;
return (
<div className="App">
<div className="main">
<img src={logo} width={250} alt="Redux Hotel" />
<h1>Your Reservation</h1>
<p>Name: {userName}</p>
<h2>Accomodation</h2>
<p><em>{accomodation.name}</em></p>
<p><img src={accomodation.image} width={300} alt="accomodation"/></p>
</div>
<SlideShow />
</div>
);
}
}

const mapStateToProps = (state) => {
const { auth, rooms } = state;
const isFetching = auth.isFetching || rooms.isFetching;


return {
isFetching,
userName: selectUserName(state),
accomodation: selectUserRoom(state)
};
};

const mapDispatchToProps = { login, fetchRooms };

export default connect(mapStateToProps, mapDispatchToProps)(App);
29 changes: 29 additions & 0 deletions episode8/src/actions/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import api from '../api/fakeApi';
import { AUTH_REQUEST, AUTH_SUCCESS, AUTH_FAILURE } from '../constants';

function authenticating() {
return {
type: AUTH_REQUEST,
};
}
function authenticate(userData) {
return {
type: AUTH_SUCCESS,
payload: userData,
};
}
function authError(error) {
return {
type: AUTH_FAILURE,
error: 'Failed to authenticate',
payload: error,
};
}

export function login() {
return (dispatch) => {
dispatch(authenticating());
return api.login()
.then((user) => dispatch(authenticate(user)));
};
}
29 changes: 29 additions & 0 deletions episode8/src/actions/rooms.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import api from '../api/fakeApi';
import { ROOMS_REQUEST, ROOMS_SUCCESS, ROOMS_FAILURE } from '../constants';

function fethingRooms() {
return {
type: ROOMS_REQUEST,
};
}
function roomsSuccess(roomsList) {
return {
type: ROOMS_SUCCESS,
payload: roomsList,
};
}
function roomsError(error) {
return {
type: ROOMS_FAILURE,
error: 'Failed to fetch rooms',
payload: error,
};
}

export function fetchRooms() {
return (dispatch) => {
dispatch(fethingRooms());
return api.fetchRooms()
.then((rooms) => dispatch(roomsSuccess(rooms)));
};
}
61 changes: 61 additions & 0 deletions episode8/src/api/fakeApi.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
const login = () => new Promise(
(resolve, reject) => {
setTimeout(() => resolve({
"firstName": "Cássio",
"lastName": "Antonio",
"gender": "Male",
"maritalStatus": "Married",
"reservation": {
"startDate": "2017-06-10T12:00",
"endDate": "2017-06-16T12:00",
"roomType": "dlxoc",
}
}), Math.random() * 100);
}
);

const fetchRooms = () => new Promise(
(resolve, reject) => {
setTimeout(() => resolve([
{
id: "stdct",
name: "City View Standard Room",
description: "1 Queen bed",
image: "http://www.hotelroomsearch.net/im/hotels/tr/room-room-hotel-6.jpg"

},
{
id: "stdoc",
name: "Ocean View Standard Room",
description: "1 Queen bed",
image: "http://www.hotelroomsearch.net/im/hotels/tr/room-room-hotel-6.jpg"
},
{
id: "dlxct",
name: "Deluxe Room, City View",
description: "2 Double beds",
image: "http://www.hotelroomsearch.net/im/hotels/tr/room-room-hotel-6.jpg"
},
{
id: "dlxoc",
name: "Deluxe Room, Ocean View",
description: "2 Double beds",
image: "http://www.hotelroomsearch.net/im/hotels/tr/room-room-hotel-6.jpg"
},
{
id: "gdlux",
name: "Grand Lux Room, Oceanfront",
description: "1 King bed and 1 Sofa bed",
image: "http://www.hotelroomsearch.net/im/hotels/tr/room-room-hotel-6.jpg"
},
{
id: "royal",
name: "Royal Suite, Oceanfront",
description: "2 king beds",
image: "http://www.hotelroomsearch.net/im/hotels/tr/room-room-hotel-6.jpg"
}
]), Math.random() * 100);
}
)

export default { login, fetchRooms };
6 changes: 6 additions & 0 deletions episode8/src/components/SlideShow.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.slideshow {
height: 100%;
width: 50%;
background-size: cover;
background-position: top left;
}
10 changes: 10 additions & 0 deletions episode8/src/components/SlideShow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react';
import background from './background.jpg';
import './SlideShow.css';

export default function SlideShow(){
return (
<div className='slideshow' style={{ backgroundImage: `url(${background})` }}>
</div>
);
};
Binary file added episode8/src/components/background.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions episode8/src/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const AUTH_REQUEST = 'AUTH_REQUEST';
export const AUTH_SUCCESS = 'AUTH_SUCCESS';
export const AUTH_FAILURE = 'AUTH_FAILURE';

export const ROOMS_REQUEST = 'ROOMS_REQUEST';
export const ROOMS_SUCCESS = 'ROOMS_SUCCESS';
export const ROOMS_FAILURE = 'ROOMS_FAILURE';
49 changes: 49 additions & 0 deletions episode8/src/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
html {
box-sizing: border-box;
text-size-adjust: 100%;
height: 100%;
}

*, *:before, *:after {
box-sizing: inherit;
}

#root {
height: 100%;
}

body {
margin: 0;
font-family: Georgia, "Times new Roman", serif;
height: 100%;
background-color: #222126;
color: #ccc;
}

h1, h2, h3, h4, h5, h6 {
font-weight: 300;
}

h1 {
font-size: 1.6em;
}

h2 {
font-size: 1.5em;
}

h3 {
font-size: 1.4em;
}

h4 {
font-size: 1.3em;
}

h5 {
font-size: 1.2em;
}

h6 {
font-size: 1.1em;
}
23 changes: 23 additions & 0 deletions episode8/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react';
import { render } from 'react-dom';
import { compose, createStore, applyMiddleware } from 'redux'
import { Provider } from 'react-redux';
import thunkMiddleware from 'redux-thunk';
import App from './App';
import reducer from './reducers';
import './index.css';

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

const store = createStore(
reducer, composeEnhancers(
applyMiddleware(thunkMiddleware)
)
);

render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
Binary file added episode8/src/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 0103151

Please sign in to comment.