mirror of
https://github.com/terribleplan/next.js.git
synced 2024-01-19 02:48:18 +00:00
Example: Form handler with Redux and React-bootstrap (#2949)
* Example: Form handler with Redux and React-bootstrap * inputChange refactoring * Destructuring inputChange
This commit is contained in:
parent
d03ce5386d
commit
4bd30c8713
30
examples/form-handler/README.md
Normal file
30
examples/form-handler/README.md
Normal file
|
@ -0,0 +1,30 @@
|
|||
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/form-handler)
|
||||
|
||||
# Form Handler
|
||||
|
||||
## How to use
|
||||
|
||||
Download the example [or clone the repo](https://github.com/zeit/next.js):
|
||||
|
||||
```bash
|
||||
curl https://codeload.github.com/zeit/next.js/tar.gz/master | tar -xz --strip=2 next.js-master/examples/form-handler
|
||||
cd form-handler
|
||||
```
|
||||
|
||||
Install it and run:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Deploy it to the cloud with [now](https://zeit.co/now) ([download](https://zeit.co/download))
|
||||
|
||||
```bash
|
||||
now
|
||||
```
|
||||
|
||||
## The idea behind the example
|
||||
|
||||
Sometimes handle multiple forms can be tricky, the idea is to have a global reducer
|
||||
with the name of each form and the inputs of it; making accessible everywhere.
|
5
examples/form-handler/actions/formActionsCreators.js
Normal file
5
examples/form-handler/actions/formActionsCreators.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
import { INPUT_VALUE } from '../constants'
|
||||
|
||||
export const inputChange = (title, name, val) => dispatch => {
|
||||
return dispatch({type: INPUT_VALUE, title, name, val})
|
||||
}
|
1
examples/form-handler/actions/index.js
Normal file
1
examples/form-handler/actions/index.js
Normal file
|
@ -0,0 +1 @@
|
|||
export * from './formActionsCreators'
|
26
examples/form-handler/components/DisplayForm.js
Normal file
26
examples/form-handler/components/DisplayForm.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
import React, {Component} from 'react'
|
||||
import { Col, Row } from 'react-bootstrap'
|
||||
import { connect } from 'react-redux'
|
||||
|
||||
class DisplayForm extends Component {
|
||||
render () {
|
||||
const { state } = this.props
|
||||
return (
|
||||
<div>
|
||||
<Row>
|
||||
<Col lg={8} lgOffset={2}>
|
||||
<pre>{JSON.stringify(state, null, 2) }</pre>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
state
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(DisplayForm)
|
17
examples/form-handler/components/Header.js
Normal file
17
examples/form-handler/components/Header.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { Col, Row, Jumbotron } from 'react-bootstrap'
|
||||
|
||||
const Header = () => {
|
||||
return (
|
||||
<div>
|
||||
<Row style={{ marginTop: '10px' }}>
|
||||
<Col lg={8} lgOffset={2}>
|
||||
<Jumbotron style={{ borderRadius: '15px' }}>
|
||||
<h1 style={{textAlign: 'center'}}>Form Handler</h1>
|
||||
</Jumbotron>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Header
|
26
examples/form-handler/components/Social.js
Normal file
26
examples/form-handler/components/Social.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
import { Col, Row } from 'react-bootstrap'
|
||||
|
||||
import Input from '../handlers/Input'
|
||||
|
||||
const Social = () => {
|
||||
return (
|
||||
<div>
|
||||
<Row>
|
||||
<Col lg={8}>
|
||||
<Input controlLabel='Facebook' title='social' name='facebook' />
|
||||
</Col>
|
||||
<Col lg={8}>
|
||||
<Input controlLabel='Instagram' title='social' name='instagram' />
|
||||
</Col>
|
||||
<Col lg={8}>
|
||||
<Input controlLabel='Twitter' title='social' name='twitter' />
|
||||
</Col>
|
||||
<Col lg={8}>
|
||||
<Input controlLabel='Github' title='social' name='github' />
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Social
|
26
examples/form-handler/components/UserForm.js
Normal file
26
examples/form-handler/components/UserForm.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
import { Col, Row } from 'react-bootstrap'
|
||||
|
||||
import Input from '../handlers/Input'
|
||||
|
||||
const UserForm = () => {
|
||||
return (
|
||||
<div>
|
||||
<Row>
|
||||
<Col lg={8} lgOffset={4}>
|
||||
<Input controlLabel='Name' title='user' name='name' />
|
||||
</Col>
|
||||
<Col lg={8} lgOffset={4}>
|
||||
<Input controlLabel='Last name' title='user' name='lastName' />
|
||||
</Col>
|
||||
<Col lg={8} lgOffset={4}>
|
||||
<Input controlLabel='Email' type='email' title='user' name='email' />
|
||||
</Col>
|
||||
<Col lg={8} lgOffset={4}>
|
||||
<Input controlLabel='Password' type='password' title='user' name='password' />
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default UserForm
|
34
examples/form-handler/components/index.js
Normal file
34
examples/form-handler/components/index.js
Normal file
|
@ -0,0 +1,34 @@
|
|||
import React, {Component} from 'react'
|
||||
import Head from 'next/head'
|
||||
import { Col, Row } from 'react-bootstrap'
|
||||
|
||||
import Header from './Header'
|
||||
import DisplayForm from './DisplayForm'
|
||||
|
||||
import UserForm from './UserForm'
|
||||
import Social from './Social'
|
||||
|
||||
class Main extends Component {
|
||||
render () {
|
||||
return (
|
||||
<div>
|
||||
<Head>
|
||||
<title>Form Handler</title>
|
||||
<link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap.min.css' />
|
||||
</Head>
|
||||
<Header />
|
||||
<DisplayForm />
|
||||
<Row>
|
||||
<Col lg={6}>
|
||||
<UserForm />
|
||||
</Col>
|
||||
<Col lg={6}>
|
||||
<Social />
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Main
|
1
examples/form-handler/constants/index.js
Normal file
1
examples/form-handler/constants/index.js
Normal file
|
@ -0,0 +1 @@
|
|||
export const INPUT_VALUE = 'INPUT_VALUE'
|
38
examples/form-handler/handlers/Input.js
Normal file
38
examples/form-handler/handlers/Input.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
import React, {Component} from 'react'
|
||||
import { FormGroup, ControlLabel, FormControl } from 'react-bootstrap'
|
||||
import { connect } from 'react-redux'
|
||||
import { bindActionCreators } from 'redux'
|
||||
|
||||
import { inputChange } from '../actions'
|
||||
|
||||
class Input extends Component {
|
||||
inputChange = (e) => {
|
||||
const { inputChange, title, name } = this.props
|
||||
inputChange(title, name, e.target.value)
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<div>
|
||||
<FormGroup controlId='formBasicText'>
|
||||
<ControlLabel>{this.props.controlLabel}</ControlLabel>
|
||||
<FormControl
|
||||
disabled={this.props.disabled}
|
||||
type={this.props.type || 'Text'}
|
||||
placeholder={this.props.controlLabel}
|
||||
onChange={this.inputChange}
|
||||
value={this.props.val}
|
||||
/>
|
||||
</FormGroup>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
inputChange: bindActionCreators(inputChange, dispatch)
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(null, mapDispatchToProps)(Input)
|
26
examples/form-handler/package.json
Normal file
26
examples/form-handler/package.json
Normal file
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "redux-form",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"start": "next start -p 8000",
|
||||
"dev": "node server.js",
|
||||
"build": "next build"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"express": "^4.15.4",
|
||||
"next": "^3.2.2",
|
||||
"next-redux-wrapper": "^1.3.2",
|
||||
"react": "^15.6.1",
|
||||
"react-bootstrap": "^0.31.3",
|
||||
"react-dom": "^15.6.1",
|
||||
"react-redux": "^5.0.6",
|
||||
"redux": "^3.7.2",
|
||||
"redux-thunk": "^2.2.0"
|
||||
}
|
||||
}
|
14
examples/form-handler/pages/index.js
Normal file
14
examples/form-handler/pages/index.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
import React, { Component } from 'react'
|
||||
import withRedux from 'next-redux-wrapper'
|
||||
|
||||
import Main from '../components'
|
||||
|
||||
import { initStore } from '../store'
|
||||
|
||||
class Index extends Component {
|
||||
render () {
|
||||
return <Main />
|
||||
}
|
||||
}
|
||||
|
||||
export default withRedux(initStore, null)(Index)
|
15
examples/form-handler/reducers/formReducer.js
Normal file
15
examples/form-handler/reducers/formReducer.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { INPUT_VALUE } from '../constants'
|
||||
|
||||
export default (state = {}, action) => {
|
||||
switch (action.type) {
|
||||
case INPUT_VALUE:
|
||||
return { ...state,
|
||||
[action.title]:
|
||||
{ ...state[action.title],
|
||||
[action.name]: action.val
|
||||
}
|
||||
}
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
6
examples/form-handler/reducers/index.js
Normal file
6
examples/form-handler/reducers/index.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
import { combineReducers } from 'redux'
|
||||
import formReducer from './formReducer'
|
||||
|
||||
export default combineReducers({
|
||||
formReducer
|
||||
})
|
28
examples/form-handler/server.js
Normal file
28
examples/form-handler/server.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
const express = require('express')
|
||||
const next = require('next')
|
||||
|
||||
const dev = process.env.NODE_ENV !== 'production'
|
||||
const app = next({ dev })
|
||||
const handle = app.getRequestHandler()
|
||||
|
||||
app.prepare()
|
||||
.then(() => {
|
||||
const server = express()
|
||||
|
||||
server.get('/', (req, res) => {
|
||||
return handle(req, res)
|
||||
})
|
||||
|
||||
server.get('*', (req, res) => {
|
||||
return handle(req, res)
|
||||
})
|
||||
|
||||
server.listen(3000, (err) => {
|
||||
if (err) throw err
|
||||
console.log('> Ready on http://localhost:3000')
|
||||
})
|
||||
})
|
||||
.catch((ex) => {
|
||||
console.error(ex.stack)
|
||||
process.exit(1)
|
||||
})
|
7
examples/form-handler/store.js
Normal file
7
examples/form-handler/store.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { createStore, applyMiddleware } from 'redux'
|
||||
import thunkMiddleware from 'redux-thunk'
|
||||
import reducer from './reducers'
|
||||
|
||||
export const initStore = (initialState = {}) => {
|
||||
return createStore(reducer, initialState, applyMiddleware(thunkMiddleware))
|
||||
}
|
Loading…
Reference in a new issue