mirror of
https://github.com/terribleplan/next.js.git
synced 2024-01-19 02:48:18 +00:00
Improve with-redux-saga example (#4392)
* Rename page component's class name: Counter => Index, Counter => Other * Rename counter component class name: AddCount => Counter * Add counter actions `decrement` and `reset` same as with-redux example * Modify page link by NavigateTo attr in Page component * Modify license MIT => ISC same as others in package.json * Modify README
This commit is contained in:
parent
e8c7dd4958
commit
b90c77b17f
|
@ -61,7 +61,7 @@ The trick here for supporting universal redux is to separate the cases for the c
|
|||
|
||||
The clock, under `components/clock.js`, has access to the state using the `connect` function from `react-redux`. In this case Clock is a direct child from the page but it could be deep down the render tree.
|
||||
|
||||
The second example, under `components/add-count.js`, shows a simple add counter function with a class component implementing a common redux pattern of mapping state and props. Again, the first render is happening in the server and instead of starting the count at 0, it will dispatch an action in redux that starts the count at 1. This continues to highlight how each navigation triggers a server render first and then a client render second, when you navigate between pages.
|
||||
The second example, under `components/counter.js`, shows a simple add counter function with a class component implementing a common redux pattern of mapping state and props. Again, the first render is happening in the server and instead of starting the count at 0, it will dispatch an action in redux that starts the count at 1. This continues to highlight how each navigation triggers a server render first and then a client render second, when you navigate between pages.
|
||||
|
||||
## What changed with next-redux-saga
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
export const actionTypes = {
|
||||
FAILURE: 'FAILURE',
|
||||
INCREMENT: 'INCREMENT',
|
||||
DECREMENT: 'DECREMENT',
|
||||
RESET: 'RESET',
|
||||
LOAD_DATA: 'LOAD_DATA',
|
||||
LOAD_DATA_SUCCESS: 'LOAD_DATA_SUCCESS',
|
||||
START_CLOCK: 'START_CLOCK',
|
||||
|
@ -18,6 +20,14 @@ export function increment () {
|
|||
return {type: actionTypes.INCREMENT}
|
||||
}
|
||||
|
||||
export function decrement () {
|
||||
return {type: actionTypes.DECREMENT}
|
||||
}
|
||||
|
||||
export function reset () {
|
||||
return {type: actionTypes.RESET}
|
||||
}
|
||||
|
||||
export function loadData () {
|
||||
return {type: actionTypes.LOAD_DATA}
|
||||
}
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
import React, {Component} from 'react'
|
||||
import {connect} from 'react-redux'
|
||||
|
||||
import {increment} from '../actions'
|
||||
|
||||
class AddCount extends Component {
|
||||
add = () => {
|
||||
this.props.dispatch(increment())
|
||||
}
|
||||
|
||||
render () {
|
||||
const {count} = this.props
|
||||
return (
|
||||
<div>
|
||||
<style jsx>{`
|
||||
div {
|
||||
padding: 0 0 20px 0;
|
||||
}
|
||||
`}</style>
|
||||
<h1>
|
||||
AddCount: <span>{count}</span>
|
||||
</h1>
|
||||
<button onClick={this.add}>Add To Count</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = ({count}) => ({count})
|
||||
export default connect(mapStateToProps)(AddCount)
|
40
examples/with-redux-saga/components/counter.js
Normal file
40
examples/with-redux-saga/components/counter.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
import React, {Component} from 'react'
|
||||
import {connect} from 'react-redux'
|
||||
|
||||
import {increment, decrement, reset} from '../actions'
|
||||
|
||||
class Counter extends Component {
|
||||
increment = () => {
|
||||
this.props.dispatch(increment())
|
||||
}
|
||||
|
||||
decrement = () => {
|
||||
this.props.dispatch(decrement())
|
||||
}
|
||||
|
||||
reset = () => {
|
||||
this.props.dispatch(reset())
|
||||
}
|
||||
|
||||
render () {
|
||||
const {count} = this.props
|
||||
return (
|
||||
<div>
|
||||
<style jsx>{`
|
||||
div {
|
||||
padding: 0 0 20px 0;
|
||||
}
|
||||
`}</style>
|
||||
<h1>
|
||||
Count: <span>{count}</span>
|
||||
</h1>
|
||||
<button onClick={this.increment}>+1</button>
|
||||
<button onClick={this.decrement}>-1</button>
|
||||
<button onClick={this.reset}>Reset</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = ({count}) => ({count})
|
||||
export default connect(mapStateToProps)(Counter)
|
|
@ -1,20 +1,20 @@
|
|||
import Link from 'next/link'
|
||||
import {connect} from 'react-redux'
|
||||
|
||||
import AddCount from './add-count'
|
||||
import Counter from './counter'
|
||||
import Clock from './clock'
|
||||
|
||||
function Page ({error, lastUpdate, light, linkTo, placeholderData, title}) {
|
||||
function Page ({error, lastUpdate, light, linkTo, NavigateTo, placeholderData, title}) {
|
||||
return (
|
||||
<div>
|
||||
<h1>
|
||||
{title}
|
||||
</h1>
|
||||
<Clock lastUpdate={lastUpdate} light={light} />
|
||||
<AddCount />
|
||||
<Counter />
|
||||
<nav>
|
||||
<Link href={linkTo}>
|
||||
<a>Navigate</a>
|
||||
<a>Navigate: {NavigateTo}</a>
|
||||
</Link>
|
||||
</nav>
|
||||
{placeholderData &&
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "with-redux-saga",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"license": "ISC",
|
||||
"scripts": {
|
||||
"dev": "next",
|
||||
"build": "next build",
|
||||
|
@ -10,7 +10,7 @@
|
|||
"dependencies": {
|
||||
"es6-promise": "4.1.1",
|
||||
"isomorphic-unfetch": "2.0.0",
|
||||
"next": "6.0.1",
|
||||
"next": "latest",
|
||||
"next-redux-saga": "3.0.0-beta.1",
|
||||
"next-redux-wrapper": "2.0.0-beta.6",
|
||||
"react": "^16.0.0",
|
||||
|
|
|
@ -2,9 +2,10 @@ import App, { Container } from 'next/app'
|
|||
import React from 'react'
|
||||
import { Provider } from 'react-redux'
|
||||
import withRedux from 'next-redux-wrapper'
|
||||
import createStore from '../store'
|
||||
import withReduxSaga from 'next-redux-saga'
|
||||
|
||||
import createStore from '../store'
|
||||
|
||||
class MyApp extends App {
|
||||
static async getInitialProps ({ Component, ctx }) {
|
||||
let pageProps = {}
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
import React from 'react'
|
||||
import {connect} from 'react-redux'
|
||||
import {increment, loadData, startClock, tickClock} from '../actions'
|
||||
|
||||
import {loadData, startClock, tickClock} from '../actions'
|
||||
import Page from '../components/page'
|
||||
|
||||
class Counter extends React.Component {
|
||||
class Index extends React.Component {
|
||||
static async getInitialProps (props) {
|
||||
const { store } = props.ctx
|
||||
store.dispatch(tickClock(props.isServer))
|
||||
store.dispatch(increment())
|
||||
const { store, isServer } = props.ctx
|
||||
store.dispatch(tickClock(isServer))
|
||||
|
||||
if (!store.getState().placeholderData) {
|
||||
store.dispatch(loadData())
|
||||
}
|
||||
|
||||
return { isServer }
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
|
@ -19,8 +21,8 @@ class Counter extends React.Component {
|
|||
}
|
||||
|
||||
render () {
|
||||
return <Page title='Index Page' linkTo='/other' />
|
||||
return <Page title='Index Page' linkTo='/other' NavigateTo='Other Page' />
|
||||
}
|
||||
}
|
||||
|
||||
export default connect()(Counter)
|
||||
export default connect()(Index)
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import React from 'react'
|
||||
import {connect} from 'react-redux'
|
||||
import {increment, startClock, tickClock} from '../actions'
|
||||
|
||||
import {startClock, tickClock} from '../actions'
|
||||
import Page from '../components/page'
|
||||
|
||||
class Counter extends React.Component {
|
||||
class Other extends React.Component {
|
||||
static async getInitialProps (props) {
|
||||
const { store, isServer } = props.ctx
|
||||
store.dispatch(tickClock(isServer))
|
||||
store.dispatch(increment())
|
||||
return { isServer }
|
||||
}
|
||||
|
||||
|
@ -16,8 +16,8 @@ class Counter extends React.Component {
|
|||
}
|
||||
|
||||
render () {
|
||||
return <Page title='Other Page' linkTo='/' />
|
||||
return <Page title='Other Page' linkTo='/' NavigateTo='Index Page' />
|
||||
}
|
||||
}
|
||||
|
||||
export default connect()(Counter)
|
||||
export default connect()(Other)
|
||||
|
|
|
@ -22,6 +22,18 @@ function reducer (state = exampleInitialState, action) {
|
|||
...{count: state.count + 1}
|
||||
}
|
||||
|
||||
case actionTypes.DECREMENT:
|
||||
return {
|
||||
...state,
|
||||
...{count: state.count - 1}
|
||||
}
|
||||
|
||||
case actionTypes.RESET:
|
||||
return {
|
||||
...state,
|
||||
...{count: exampleInitialState.count}
|
||||
}
|
||||
|
||||
case actionTypes.LOAD_DATA_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import {createStore, applyMiddleware} from 'redux'
|
||||
import createSagaMiddleware from 'redux-saga'
|
||||
|
||||
import rootReducer, {exampleInitialState} from './reducer'
|
||||
import rootSaga from './saga'
|
||||
|
||||
|
@ -13,7 +14,7 @@ const bindMiddleware = (middleware) => {
|
|||
return applyMiddleware(...middleware)
|
||||
}
|
||||
|
||||
export function configureStore (initialState = exampleInitialState) {
|
||||
function configureStore (initialState = exampleInitialState) {
|
||||
const store = createStore(
|
||||
rootReducer,
|
||||
initialState,
|
||||
|
|
Loading…
Reference in a new issue