-
Notifications
You must be signed in to change notification settings - Fork 298
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
27 changed files
with
510 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Redux Thunk Tricks | ||
|
||
ReactCasts, episode 10. | ||
|
||
Redux Thunk is the most used library for side effects and asyncronous calls in Redux - and that's for a reason. But despite being so used, there are a few useful thunk tricks that aren't yet commonplace, so in this episode I'll share some pieces of thunk knowledge that might help you build better applications. | ||
|
||
Screencast video: | ||
https://youtu.be/xihoZZU0gao | ||
|
||
# Outline | ||
|
||
- The first tip is very simple: You can return values from thunks, and this can be useful, for example, for asynchronous orchestration. | ||
|
||
- The second tip is about thunk's getState, and how it can be a bad idea to rely on this mechanism for accessing data. | ||
|
||
- The third tip is about using thunk withExtraArguments to make your thunks easy to test and run on multiple environments. | ||
|
||
|
||
# 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 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
"name": "bookstore", | ||
"version": "0.1.0", | ||
"private": true, | ||
"dependencies": { | ||
"lodash.intersection": "^4.4.0", | ||
"react": "^15.5.4", | ||
"react-dom": "^15.5.4", | ||
"react-redux": "^5.0.4", | ||
"redux": "^3.6.0", | ||
"semantic-ui-react": "^0.68.2" | ||
}, | ||
"devDependencies": { | ||
"react-scripts": "0.9.5" | ||
}, | ||
"scripts": { | ||
"start": "react-scripts start", | ||
"build": "react-scripts build", | ||
"test": "react-scripts test --env=jsdom", | ||
"eject": "react-scripts eject" | ||
} | ||
} |
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.
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.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.2/semantic.min.css"></link> | ||
<!-- | ||
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import React, { Component } from 'react'; | ||
import { Dropdown, Segment } from 'semantic-ui-react' | ||
import Auth from './components/Auth'; | ||
import BookDetails from './components/BookDetails'; | ||
|
||
class App extends Component { | ||
state = { | ||
selectedId: null | ||
} | ||
render() { | ||
return ( | ||
<div> | ||
<Auth /> | ||
{ this.state.selectedId ? | ||
<BookDetails id={this.state.selectedId} /> | ||
: | ||
<Segment> | ||
<Dropdown | ||
placeholder='Select a Book' | ||
options={[ | ||
{ text: 'Harry Potter', value: 1 }, | ||
{ text: 'Lord of the Rings', value: 2 }, | ||
{ text: 'Game of Thrones', value: 3 }, | ||
{ text: 'Sherlock Holmes', value: 4 }, | ||
{ text: 'Murder in the Orient Express', value: 5 }, | ||
{ text: 'Neuromancer', value: 6 }, | ||
{ text: 'Ready Player One', value: 7 }, | ||
]} | ||
onChange={(e, selected)=> this.setState({selectedId: selected.value})} | ||
fluid | ||
search | ||
selection | ||
/> | ||
</Segment> | ||
} | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
export default App; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { | ||
BOOK_REQUESTING, BOOK_SUCCESS, BOOK_FAILURE, SIMILAR_REQUESTING, SIMILAR_SUCCESS, SIMILAR_FAILURE | ||
} from '../constants'; | ||
|
||
const entryLoading = id => ({ type: BOOK_REQUESTING, payload: id }); | ||
const entryLoaded = book => ({ type: BOOK_SUCCESS, payload: book }); | ||
const entryLoadError = () => ({ type: BOOK_FAILURE }); | ||
|
||
export const requestBook = id => ( | ||
(dispatch, getState, api) => { | ||
dispatch(entryLoading(id)); | ||
return api.fetchBook(id) | ||
.then(book => { | ||
dispatch( entryLoaded(book) ); | ||
return book; | ||
}) | ||
.catch(err => { | ||
dispatch( entryLoadError() ); | ||
}); | ||
} | ||
); | ||
|
||
const similarEntriesLoading = tags => ({ type: SIMILAR_REQUESTING, payload: tags }); | ||
const similarEntriesLoaded = books => ({ type: SIMILAR_SUCCESS, payload: books }); | ||
const similarEntriesLoadError = () => ({ type: SIMILAR_FAILURE }); | ||
|
||
export const requestBooksByTags = (id, tags) => ( | ||
(dispatch, getState, api) => { | ||
dispatch(similarEntriesLoading(tags)); | ||
api.fetchBooksByTags(tags) | ||
.then(books => { | ||
dispatch( similarEntriesLoaded(books.filter(p => p.id !== id)) ); | ||
}) | ||
.catch(err => { | ||
dispatch( similarEntriesLoadError() ); | ||
}); | ||
} | ||
); | ||
|
||
|
||
export const requestBookAndSimilars = (id) => ( | ||
dispatch => { | ||
dispatch(requestBook(id)).then(book => dispatch(requestBooksByTags(id, book.tags))); | ||
} | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { ADDED_TO_CART } from '../constants'; | ||
|
||
const added = id => ({ type: ADDED_TO_CART, payload: id }); | ||
|
||
export const addToCart = (bookId) => ( | ||
(dispatch, getState, api) => { | ||
const user = getState().user; | ||
if(user){ | ||
api.addToCart(bookId) | ||
.then(dispatch(added(bookId))); | ||
} | ||
} | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { | ||
LOG_USER, LOGGED_USER, USER_FAILURE | ||
} from '../constants'; | ||
|
||
const userLoading = id => ({ type: LOG_USER, payload: id }); | ||
const userLoaded = user => ({ type: LOGGED_USER, payload: user }); | ||
const userLoadError = () => ({ type: USER_FAILURE }); | ||
|
||
export const getUser = () => ( | ||
(dispatch, getState, api) => { | ||
dispatch(userLoading); | ||
return api.getUser() | ||
.then(user => { | ||
dispatch( userLoaded(user) ); | ||
return user; | ||
}) | ||
.catch(err => { | ||
dispatch( userLoadError() ); | ||
}); | ||
} | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import intersection from 'lodash.intersection'; | ||
|
||
const books = [ | ||
{ | ||
id: 1, | ||
series: 'Harry Potter', | ||
title: 'Harry Potter and the Philosopher\'s Stone', | ||
author: 'J. K. Rowling', | ||
image: `${process.env.PUBLIC_URL}/books/harrypotter.jpg`, | ||
tags: ['fantasy', 'magic', 'puberty'] | ||
}, | ||
{ | ||
id: 2, | ||
series: 'Lord of the Rings', | ||
title: 'The fellowship of the Ring', | ||
author: 'J. R. R. Tolkien', | ||
image: `${process.env.PUBLIC_URL}/books/lotr.jpg`, | ||
tags: ['fantasy', 'magic', 'jewelry'] | ||
}, | ||
{ | ||
id: 3, | ||
series: 'Game of Thrones', | ||
title: 'A Song of Ice and Fire', | ||
author: 'George R. R. Martin', | ||
image: `${process.env.PUBLIC_URL}/books/gameofthrones.jpg`, | ||
tags: ['fantasy', 'killing everyone you will care about'] | ||
}, | ||
{ | ||
id: 4, | ||
series: 'Sherlock Holmes', | ||
title: 'The adventures of Sherlock Holmes', | ||
author: 'Arthur Conan Doyle', | ||
image: `${process.env.PUBLIC_URL}/books/sherlockholmes.jpg`, | ||
tags: ['detective', 'crime', 'drug abuse'] | ||
}, | ||
{ | ||
id: 5, | ||
title: 'Murder on the Orient Express', | ||
author: 'Agatha Cristie', | ||
image: `${process.env.PUBLIC_URL}/books/murderorient.jpg`, | ||
tags: ['detective', 'crime', 'tourism'] | ||
}, | ||
{ | ||
id: 6, | ||
title: 'Neuromancer', | ||
author: 'William Gibson', | ||
image: `${process.env.PUBLIC_URL}/books/neuromancer.jpg`, | ||
tags: ['science fiction', 'matrix', 'cowboys'] | ||
}, | ||
{ | ||
id: 7, | ||
title: 'Ready Player One', | ||
author: 'Ernest Cline', | ||
image: `${process.env.PUBLIC_URL}/books/readyp1.jpg`, | ||
tags: ['science fiction', 'matrix', 'insert coin'] | ||
}, | ||
]; | ||
|
||
const fetchBook = id => { | ||
const book = books.find(book => book.id === parseInt(id, 10)); | ||
return fakeRequest(book); | ||
}; | ||
|
||
const fetchBooksByTags = tags => { | ||
const similar = books.filter(p => intersection(p.tags, tags).length > 0) | ||
return fakeRequest(similar); | ||
}; | ||
|
||
const getUser = () => { | ||
return fakeRequest({id: 1, name: 'cassiozen', token: 'k536kh36kh456h4536'}); | ||
}; | ||
|
||
const addToCart = (id) => { | ||
return fakeRequest(); | ||
}; | ||
|
||
// Returns a promise for data that resolves after a random timeout (0 to 500 ms). | ||
function fakeRequest(data) { | ||
return new Promise(resolve => { | ||
setTimeout(()=>{ | ||
resolve(data); | ||
}, (Math.random() * 100)); | ||
}) | ||
}; | ||
|
||
|
||
export default { fetchBook, fetchBooksByTags, getUser, addToCart }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import React, { Component } from 'react'; | ||
import { connect } from 'react-redux'; | ||
import { getUser } from '../actions/user'; | ||
import { Button } from 'semantic-ui-react' | ||
|
||
class Auth extends Component { | ||
render() { | ||
const { user, getUser } = this.props | ||
return ( | ||
<Button onClick={getUser}> | ||
{ user? 'Logged' : 'Login' } | ||
</Button> | ||
) | ||
} | ||
} | ||
|
||
const mapStateToProps = (state) => { | ||
return { user: state.user }; | ||
} | ||
|
||
const mapDispatchToProps = { | ||
getUser | ||
} | ||
|
||
export default connect(mapStateToProps, mapDispatchToProps)(Auth); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
.cover { | ||
display: block; | ||
height: 305px; | ||
float: left; | ||
margin-right: 15px; | ||
} | ||
|
||
.segment::after { | ||
content: ''; | ||
display: block; | ||
clear: both; | ||
} | ||
|
||
.similar { | ||
margin-top: 29px; | ||
} | ||
|
||
.similar_cover { | ||
display: block; | ||
height: 125px; | ||
float: left; | ||
margin-right: 15px; | ||
} | ||
|
||
.segment .ui.button { | ||
display: block; | ||
margin: 15px 0; | ||
} |
Oops, something went wrong.