Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(WIP) Update examples #1800

Closed
wants to merge 46 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
3ddb19f
basic universal example with react-router and react-router-redux
xulien Feb 15, 2016
c8ab126
cleaning
xulien Feb 15, 2016
bf0fafb
update to react-router-redux 4.x
xulien Feb 15, 2016
46dd120
cleaning
xulien Feb 15, 2016
6426b3f
cleaning
xulien Feb 15, 2016
f7ec1a9
init
xulien Feb 17, 2016
e50bcad
async-router example
xulien Feb 17, 2016
0fd5f12
async-with-routing example
xulien Feb 17, 2016
7393f90
cleaning
xulien Feb 17, 2016
81b8006
cleaning
xulien Feb 17, 2016
40f6ec6
delete universal-with-router based on counter example
xulien Feb 17, 2016
25cfc5a
cleaning
xulien Feb 17, 2016
41932f1
simplification of the routing
xulien Feb 17, 2016
4dc3944
title update
xulien Feb 17, 2016
53a594b
linting
xulien Feb 17, 2016
2c42ba8
linting
xulien Feb 18, 2016
d05f8d2
name and description update
xulien Feb 18, 2016
0dc353f
async-universal example
xulien Feb 18, 2016
30e4d80
generic index route
xulien Feb 23, 2016
4033f7d
cleaning
xulien Feb 23, 2016
35fcf27
generic index route
xulien Feb 23, 2016
c91dccb
Layout.js removed
xulien Mar 11, 2016
71d55cf
intermediate refactoring
xulien Mar 11, 2016
9633ecf
cleaning
xulien Mar 11, 2016
c8bfd67
move fetchdata into container
xulien Mar 11, 2016
ad054bb
cleaning
xulien Mar 11, 2016
a1f2d63
remove transform-class-properties
xulien Apr 12, 2016
545b288
remove static keyword
xulien Apr 12, 2016
a489327
missing space
xulien Apr 12, 2016
d4604bb
typo
xulien Apr 12, 2016
110489e
remove unused import
xulien Apr 12, 2016
5b96f84
Remove hacks to alias Redux to src folder in examples
xulien Apr 12, 2016
50ef70c
Per-file ESLint exceptions removed
xulien Apr 12, 2016
bf3b17a
Layout.js renamed to App.js
xulien Apr 12, 2016
6890c4a
Remove NoErrorsPlugin
xulien Apr 12, 2016
38105ca
Remove NoErrorsPlugin
xulien Apr 12, 2016
a424585
compile redux from source is needed here
xulien Apr 12, 2016
6a5d6e6
App component with kind of header added
xulien Apr 12, 2016
a56fcbb
indentation
xulien Apr 12, 2016
2f3cad8
babel-preset-react-hmre removed
xulien Apr 12, 2016
35469d4
es5 version for the sake of consistency
xulien Apr 14, 2016
052c8d7
Merge https://github.com/reactjs/redux
xulien Apr 21, 2016
6cc5f17
Merge pull request #1403 from xulien/master
gaearon Jun 11, 2016
0a5ea48
Start updating async example (wip)
gaearon Jun 12, 2016
7387504
Modernize async example setup
gaearon Jun 12, 2016
f7b5220
Modernize counter example setup
mxstbr Jun 14, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions examples/async-universal/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"presets": ["es2015", "react"]
}
21 changes: 21 additions & 0 deletions examples/async-universal/client/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import 'babel-polyfill'
import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { Router, browserHistory } from 'react-router'

import configureStore from '../common/store/configureStore'
import routes from '../common/routes'

const initialState = window.__INITIAL_STATE__
const store = configureStore(initialState)
const rootElement = document.getElementById('app')

render(
<Provider store={store}>
<Router history={browserHistory}>
{routes}
</Router>
</Provider>,
rootElement
)
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function requestPosts(reddit) {
function receivePosts(reddit, json) {
return {
type: RECEIVE_POSTS,
reddit,
reddit: reddit,
posts: json.data.children.map(child => child.data),
receivedAt: Date.now()
}
Expand Down
16 changes: 16 additions & 0 deletions examples/async-universal/common/components/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React, { Component } from 'react'

export default class App extends Component {
render() {
return (
<div>
<div>
<h3>Redux async universal example</h3>
<p>Code on <a href="https://github.com/reactjs/redux">Github</a></p>
<hr/>
</div>
{this.props.children}
</div>
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default class Picker extends Component {

return (
<span>
<h1>{value}</h1>
<h1>{(value) ? value : 'Select a subreddit below'}</h1>
<select onChange={e => onChange(e.target.value)}
value={value}>
{options.map(option =>
Expand Down
115 changes: 115 additions & 0 deletions examples/async-universal/common/containers/Reddit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import { selectReddit, fetchPostsIfNeeded, invalidateReddit } from '../actions'
import Picker from '../components/Picker'
import Posts from '../components/Posts'

class Reddit extends Component {

constructor(props) {
super(props)
this.handleChange = this.handleChange.bind(this)
this.handleRefreshClick = this.handleRefreshClick.bind(this)
}

componentWillReceiveProps(nextProps) {
const { dispatch, params } = this.props

if (nextProps.params.id !== params.id) {
dispatch(selectReddit(nextProps.params.id))
if (nextProps.params.id) {
dispatch(fetchPostsIfNeeded(nextProps.params.id))
}
}

}

handleChange(nextReddit) {
this.context.router.push(`/${nextReddit}`)
}

handleRefreshClick(e) {
e.preventDefault()

const { dispatch, selectedReddit } = this.props
dispatch(invalidateReddit(selectedReddit))
dispatch(fetchPostsIfNeeded(selectedReddit))
}

render() {
const { selectedReddit, posts, isFetching, lastUpdated } = this.props
const isEmpty = posts.length === 0
return (
<div>
<Picker value={selectedReddit}
onChange={this.handleChange}
options={ [ '', 'reactjs', 'frontend' ] } />
<p>
{lastUpdated &&
<span>
Last updated at {new Date(lastUpdated).toLocaleTimeString()}.
{' '}
</span>
}
{!isFetching && selectedReddit &&
<a href="#"
onClick={this.handleRefreshClick}>
Refresh
</a>
}
</p>
{isEmpty
? (isFetching ? <h2>Loading...</h2> : <h2>Empty.</h2>)
: <div style={{ opacity: isFetching ? 0.5 : 1 }}>
<Posts posts={posts}/>
</div>
}
</div>
)
}
}

Reddit.fetchData = (dispatch, params) => {
const subreddit = params.id
if (subreddit) {
return Promise.all([
dispatch(selectReddit(subreddit)),
dispatch(fetchPostsIfNeeded(subreddit))
])
} else {
return Promise.resolve()
}
}

Reddit.contextTypes = {
router: PropTypes.object
}

Reddit.propTypes = {
selectedReddit: PropTypes.string.isRequired,
posts: PropTypes.array.isRequired,
isFetching: PropTypes.bool.isRequired,
lastUpdated: PropTypes.number,
dispatch: PropTypes.func.isRequired
}

function mapStateToProps(state) {
const { selectedReddit, postsByReddit } = state
const {
isFetching,
lastUpdated,
items: posts
} = postsByReddit[selectedReddit] || {
isFetching: false,
items: []
}

return {
selectedReddit,
posts,
isFetching,
lastUpdated
}
}

export default connect(mapStateToProps)(Reddit)
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import {
REQUEST_POSTS, RECEIVE_POSTS
} from '../actions'

function selectedReddit(state = 'reactjs', action) {
function selectedReddit(state = '', action) {
switch (action.type) {
case SELECT_REDDIT:
return action.reddit
return action.reddit || ''
default:
return state
}
Expand Down
13 changes: 13 additions & 0 deletions examples/async-universal/common/routes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react'
import Route from 'react-router/lib/Route'
import IndexRoute from 'react-router/lib/IndexRoute'

import App from './components/App'
import Reddit from './containers/Reddit'

export default (
<Route path="/" component={App}>
<IndexRoute component={Reddit}/>
<Route path=":id" component={Reddit}/>
</Route>
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import thunkMiddleware from 'redux-thunk'
import createLogger from 'redux-logger'
import rootReducer from '../reducers'

export default function configureStore(preloadedState) {
export default function configureStore(initialState) {
const store = createStore(
rootReducer,
preloadedState,
initialState,
applyMiddleware(thunkMiddleware, createLogger())
)

Expand Down
52 changes: 52 additions & 0 deletions examples/async-universal/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"name": "redux-async-universal-example",
"version": "0.0.0",
"description": "Redux async universal example",
"scripts": {
"start": "node server/index.js"
},
"repository": {
"type": "git",
"url": "https://github.com/reactjs/redux.git"
},
"keywords": [
"react",
"reactjs",
"hot",
"reload",
"hmr",
"live",
"edit",
"webpack",
"flux"
],
"license": "MIT",
"bugs": {
"url": "https://github.com/reactjs/redux/issues"
},
"homepage": "http://redux.js.org",
"dependencies": {
"babel-polyfill": "^6.3.14",
"express": "^4.13.4",
"isomorphic-fetch": "^2.1.1",
"react": "^0.14.7",
"react-dom": "^0.14.7",
"react-redux": "^4.2.1",
"react-router": "^2.0.0",
"redux": "^3.2.1",
"redux-logger": "^2.4.0",
"redux-thunk": "^1.0.3"
},
"devDependencies": {
"babel-core": "^6.3.15",
"babel-loader": "^6.2.0",
"babel-preset-es2015": "^6.3.13",
"babel-preset-react": "^6.3.13",
"expect": "^1.6.0",
"node-libs-browser": "^0.5.2",
"react-transform-hmr": "^1.0.4",
"webpack": "^1.9.11",
"webpack-dev-middleware": "^1.2.0",
"webpack-hot-middleware": "^2.2.0"
}
}
2 changes: 2 additions & 0 deletions examples/async-universal/server/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
require('babel-register')
require('./server')
80 changes: 80 additions & 0 deletions examples/async-universal/server/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
var webpack = require('webpack')
var webpackDevMiddleware = require('webpack-dev-middleware')
var webpackHotMiddleware = require('webpack-hot-middleware')
var config = require('../webpack.config')
var React = require('react')
var renderToString = require('react-dom/server').renderToString
var Provider = require('react-redux').Provider
var match = require('react-router/lib/match')
var RouterContext = require('react-router/lib/RouterContext')

var configureStore = require('../common/store/configureStore').default
var routes = require('../common/routes').default

var app = new (require('express'))()
var port = 3000

var compiler = webpack(config)
app.use(webpackDevMiddleware(compiler, { noInfo: true, publicPath: config.output.publicPath }))
app.use(webpackHotMiddleware(compiler))

app.use(handleRender)

function handleRender(req, res) {
match({ routes, location: req.url }, function(error, redirectLocation, renderProps) {
if (error) {
res.status(500).send(error.message)
} else if (redirectLocation) {
res.redirect(302, redirectLocation.pathname + redirectLocation.search)
} else if (renderProps) {
// Create a new Redux store instance
var store = configureStore()

// Grab static fetchData
var fetchData = renderProps.components[ renderProps.components.length - 1 ].fetchData

// Query our API asynchronously
fetchData(store.dispatch, renderProps.params).then(() => {

const html = renderToString(
<Provider store={store}>
<RouterContext { ...renderProps} />
</Provider>
)

var finalState = store.getState()

res.status(200).send(renderFullPage(html, finalState))
})

} else {
res.status(404).send('Not found')
}
})
}

function renderFullPage(html, initialState) {
return `
<!doctype html>
<html>
<head>
<title>Redux Async Universal Example</title>
</head>
<body>
<div id="app">${html}</div>
<script>
window.__INITIAL_STATE__ = ${JSON.stringify(initialState)}
</script>
<script src="/static/bundle.js"></script>
</body>
</html>
`
}

app.listen(port, function(error) {
if (error) {
console.error(error)
} else {
console.info("==> 🌎 Listening on port %s. Open up http://localhost:%s/ in your browser.", port, port)
}
})
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,25 @@ module.exports = {
devtool: 'cheap-module-eval-source-map',
entry: [
'webpack-hot-middleware/client',
'./index'
'./client/index.js'
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: '/static/'
},
plugins: [
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin()
],
module: {
loaders: [
{
test: /\.js$/,
loaders: [ 'babel' ],
loaders: ['babel'],
exclude: /node_modules/,
include: __dirname
}
]
}
}
}
8 changes: 8 additions & 0 deletions examples/async-with-routing/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"presets": ["es2015", "react"],
"env": {
"development": {
"presets": ["react-hmre"]
}
}
}
Loading