<!DOCTYPE html>
<html>
<head>
<link data-require="bootstrap@4.0.5" data-semver="4.0.5" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" />
<link rel="stylesheet" href="style.css" />
<script data-require="lodash.js@4.17.4" data-semver="4.17.4" src="https://cdn.jsdelivr.net/npm/lodash@4.17.4/lodash.min.js"></script>
<script src="https://jspm.io/system@0.18.js"></script>
<script src="config.js"></script>
<script>
System.import('app').catch(console.error.bind(console));
</script>
</head>
<body>
<div id="app"></div>
</body>
</html>
.list-group,
.book-details {
margin: 30px auto;
}
.book-details {
padding: 30px;
}
.list-group-item {
cursor: pointer;
}
.list-group-item:hover {
background-color: #eee;
}
/*global System */
'use strict';
System.config({
transpiler: 'babel',
map: {
'react': 'https://unpkg.com/react@15.3.2/dist/react.min.js',
'react-dom': 'https://unpkg.com/react-dom@15.3.2/dist/react-dom.min.js',
'redux': 'https://unpkg.com/redux@3.7.2/dist/redux.min.js',
'react-redux': 'https://unpkg.com/react-redux@5.0.6/dist/react-redux.min.js',
//'axios': 'https://unpkg.com/axios/dist/axios.min.js',
'app': './src'
},
packages: {
app: {
main: './index.jsx',
defaultExtension: false,
},
}
});
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { createStore } from "redux";
import App from "./components/app.jsx";
import reducers from "./reducers/index.jsx";
ReactDOM.render(
<Provider store={createStore(reducers)}>
<App />
</Provider>,
document.querySelector("#app")
);
import React, { Component } from "react";
import { connect } from "react-redux";
import { selectBook } from "../actions/index.jsx";
import { bindActionCreators } from "redux";
class BookList extends Component {
renderList() {
return this.props.books.map(book => {
return (
<li
key={book.title}
onClick={() => this.props.selectBook(book)}
className="list-group-item"
>
{book.title}
</li>
);
});
}
render() {
return (
<ul className="list-group col-sm-4">
{this.renderList()}
</ul>
);
}
}
function mapStateToProps(state) {
// Whatever is returned will show up as props
// inside of BookList
return {
books: state.books
};
}
// Anything returned from this function will end up as props
// on the BookList container
function mapDispatchToProps(dispatch) {
// Whenever selectBook is called, the result shoudl be passed
// to all of our reducers
return bindActionCreators({ selectBook: selectBook }, dispatch);
}
// Promote BookList from a component to a container - it needs to know
// about this new dispatch method, selectBook. Make it available
// as a prop.
export default connect(mapStateToProps, mapDispatchToProps)(BookList);
import React from "react";
import { Component } from "react";
import BookList from "../containers/book-list.jsx";
import BookDetail from "../containers/book-detail.jsx";
export default class App extends Component {
render() {
return (
<div>
<BookList />
<BookDetail />
</div>
);
}
}
export function selectBook(book) {
// selectBook is an ActionCreator, it needs to return an action,
// an object with a type property.
return {
type : "BOOK_SELECTED",
payload : book
};
}
import { combineReducers } from "redux";
import BooksReducer from "./reducer_books.jsx";
import ActiveBook from "./reducer_active_book.jsx";
const rootReducer = combineReducers({
books : BooksReducer,
activeBook : ActiveBook
});
export default rootReducer;
export default function() {
return [
{ title: "Javascript: The Good Parts", pages: 101 },
{ title: "Harry Potter", pages: 39 },
{ title: "The Dark Tower", pages: 85 },
{ title: "Eloquent Ruby", pages: 1 }
];
}
// State argument is not application state, only the state
// this reducer is responsible for
export default function(state = null, action) {
switch (action.type) {
case "BOOK_SELECTED":
return action.payload;
}
return state;
}
import React, { Component } from "react";
import { connect } from "react-redux";
class BookDetail extends Component {
render() {
if (!this.props.book) {
return (
<div className="book-details">
Please select a book from above to get started.
</div>
);
}
return (
<div className="book-details">
<h3>Details for:</h3>
<div>Title: {this.props.book.title}</div>
<div>Pages: {this.props.book.pages}</div>
</div>
);
}
}
function mapStateToProps(state) {
return {
book: state.activeBook
};
}
export default connect(mapStateToProps)(BookDetail);