forked from redux-form/redux-form
-
Notifications
You must be signed in to change notification settings - Fork 0
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
Erik Rasmussen
committed
Jul 31, 2015
0 parents
commit e09ce68
Showing
19 changed files
with
438 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,4 @@ | ||
{ | ||
"stage": 0, | ||
"loose": "all" | ||
} |
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 @@ | ||
node_modules |
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 @@ | ||
{ | ||
"extends": "eslint-config-airbnb", | ||
"env": { | ||
"browser": true, | ||
"mocha": true, | ||
"node": true | ||
}, | ||
"rules": { | ||
"react/jsx-uses-react": 2, | ||
"react/jsx-uses-vars": 2, | ||
"react/react-in-jsx-scope": 2, | ||
|
||
//Temporarirly disabled due to a possible bug in babel-eslint (todomvc example) | ||
"block-scoped-var": 0, | ||
// Temporarily disabled for test/* until babel/babel-eslint#33 is resolved | ||
"padded-blocks": 0 | ||
}, | ||
"plugins": [ | ||
"react" | ||
] | ||
} |
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,5 @@ | ||
.idea | ||
node_modules | ||
dist | ||
lib | ||
.DS_Store |
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,2 @@ | ||
src | ||
examples |
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 @@ | ||
The MIT License (MIT) | ||
|
||
Copyright (c) 2015 Erik Rasmussen | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
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,133 @@ | ||
#redux-form | ||
|
||
|
||
`@reduxForm` is an ES7 decorator to for enabling a form in [React](https://github.com/facebook/react) to use [Redux](https://github.com/gaearon/redux) to store all of | ||
its state. | ||
|
||
## Installation | ||
|
||
``` | ||
npm install --save redux-form | ||
``` | ||
|
||
## Benefits | ||
|
||
Why would anyone want to do this, you ask? React a perfectly good way of keeping state in each component! The reasons are twofold. | ||
|
||
#### Hot Reloading | ||
|
||
When used in conjunction with [React Hot Loader](https://github.com/gaearon/react-hot-loader), you can modify your components, rebuild your app and immediately see your changes ***without losing your form data***. This may seem trivial, but the minutes of refilling out forms in a develomnet environment really add up. | ||
|
||
#### Stateless Components | ||
|
||
By removing the state from your form components, you inherently make them easier to understand, test, and debug. The React philosophy is to always try to use `props` instead of `state` when possible. | ||
|
||
## How it works | ||
|
||
When you are adding your reducers to your redux store, add a new one with `createFormReducer(])`. | ||
|
||
```javascript | ||
import { createStore, combineReducers } from 'redux'; | ||
import { createFormReducer } from 'redux-form'; | ||
const reducers = { | ||
// ... your other reducers here ... | ||
createFormReducer('contacts', ['name', 'address', 'phone'], contactValidation) | ||
} | ||
const reducer = combineReducers(reducers); | ||
const store = createStore(reducer); | ||
``` | ||
|
||
Then, on your form component, add the `@reduxForm('contacts')` decorator. | ||
|
||
```javascript | ||
import React, {Component, PropTypes} from 'react'; | ||
import reduxForm from 'redux-form'; | ||
|
||
@reduxForm('contacts') | ||
export default class ContactForm extends Component { | ||
static propTypes = { | ||
data: PropTypes.object.isRequired, | ||
errors: PropTypes.object.isRequired, | ||
handleChange: PropTypes.func.isRequired, | ||
validate: PropTypes.func.isRequired, | ||
reset: PropTypes.func.isRequired | ||
} | ||
|
||
render() { | ||
const { | ||
data: {name, address, phone}, | ||
errors: {name: nameError, address: addressError, phone: phoneError} | ||
} = this.props; | ||
return ( | ||
<form> | ||
<label>Name</label> | ||
<input type="text" value={name} onChange={handleChange('name')}/> | ||
{nameError ? <div>{nameError}</div>} | ||
|
||
<label>Address</label> | ||
<input type="text" value={address} onChange={handleChange('address')}/> | ||
{addressError ? <div>{addressError}</div>} | ||
|
||
<label>Phone</label> | ||
<input type="text" value={phone} onChange={handleChange('phone')}/> | ||
{phoneError ? <div>{phoneError}</div>} | ||
</form> | ||
); | ||
} | ||
} | ||
``` | ||
Notice that we're just using vanilla `<input>` elements there is no state in the `ContactForm` component. I have left handling `onSubmit` as an excercise for the reader. Hint: your data is in `this.props.data`. | ||
## Validation | ||
You will need to supply your own validation function, which is in the form `({}) => {}` and takes in all your data and spits out error messages. For example: | ||
```javascript | ||
function contactValidation(data) { | ||
const errors = {}; | ||
if(!data.name) { | ||
errors.name = 'Required'; | ||
} | ||
if(data.address && data.address.length > 50) { | ||
errors.address = 'Must be fewer than 50 characters'; | ||
} | ||
if(!data.phone) { | ||
errors.phone = 'Required'; | ||
} else if(!/\d{3}-\d{3}-\d{4}/.test(data.phone)) { | ||
errors.phone = 'Phone must match the form "999-999-9999"' | ||
} | ||
return errors; | ||
} | ||
``` | ||
You get the idea. | ||
## API | ||
Each form has a `sliceName`. That's the key in the Redux store tree where the data will be mounted. | ||
### createFormReducer(sliceName:string, fields:Array<string>, validate:Function) | ||
##### -`sliceName` : string | ||
> the name of your form and the key to where your form's state will be mounted in the Redux store | ||
##### - fields : Array<string> | ||
> a list of all your fields in your form. | ||
##### - validation : Function | ||
> your [validation function](#validation) | ||
### @reduxForm(sliceName:string) | ||
##### -`sliceName` : string | ||
> the name of your form and the key to where your form's state will be mounted in the Redux store | ||
## Running Example | ||
Check out the [react-redux-universal-hot-example project](https://github.com/erikras/react-redux-universal-hot-example) to see `redux-form` in action. | ||
This is an extremely young library, so the API may change. Comments and feedback welcome. |
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,48 @@ | ||
{ | ||
"name": "redux-form", | ||
"version": "0.0.2", | ||
"description": "An ES7 decorator for forms using Redux and React", | ||
"main": "./lib/index.js", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/erikras/redux-form" | ||
}, | ||
"scripts": { | ||
"browser": "scripts/browser", | ||
"build": "scripts/build", | ||
"clean": "scripts/clean", | ||
"lint": "scripts/lint", | ||
"prepublish": "scripts/prepublish" | ||
}, | ||
"keywords": [ | ||
"react", | ||
"reactjs", | ||
"flux", | ||
"redux", | ||
"form", | ||
"decorator" | ||
], | ||
"author": "Erik Rasmussen <[email protected]> (http://github.com/erikras)", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/erikras/redux-form/issues" | ||
}, | ||
"homepage": "https://github.com/erikras/redux-form", | ||
"devDependencies": { | ||
"babel": "^5.8.19", | ||
"babel-core": "^5.8.19", | ||
"babel-eslint": "^4.0.5", | ||
"babel-loader": "^5.3.2", | ||
"eslint": "^0.24.1", | ||
"eslint-config-airbnb": "0.0.6", | ||
"eslint-plugin-react": "^3.1.0", | ||
"react": "^0.13.3", | ||
"rifraf": "^2.0.2", | ||
"rimraf": "^2.4.2", | ||
"webpack": "^1.10.5" | ||
}, | ||
"dependencies": { | ||
"react-redux": "^0.2.2", | ||
"redux": "^1.0.0-rc" | ||
} | ||
} |
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,8 @@ | ||
#!/bin/sh -e | ||
|
||
WEBPACK_CMD=node_modules/.bin/webpack | ||
|
||
mkdir -p dist | ||
|
||
$WEBPACK_CMD src/index.js dist/react-redux.js | ||
NODE_ENV=production $WEBPACK_CMD src/index.js dist/react-redux.min.js |
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,4 @@ | ||
#!/bin/sh -e | ||
|
||
rm -rf lib | ||
`npm bin`/babel src --out-dir lib |
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,3 @@ | ||
#!/bin/sh | ||
|
||
`npm bin`/rimraf ./lib |
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,3 @@ | ||
#!/bin/sh | ||
|
||
`npm bin`/eslint src |
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,6 @@ | ||
#!/bin/sh -e | ||
|
||
sh scripts/lint | ||
sh scripts/clean | ||
sh scripts/browser | ||
sh scripts/build |
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,3 @@ | ||
export const CHANGE = 'REDUX_FORM_CHANGE'; | ||
export const VALIDATE = 'REDUX_FORM_VALIDATE'; | ||
export const RESET = 'REDUX_FORM_RESET'; |
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,24 @@ | ||
import { CHANGE, VALIDATE, RESET } from './actionTypes'; | ||
|
||
export function change(form, field, value) { | ||
return { | ||
type: CHANGE, | ||
form: form, | ||
field: field, | ||
value: value | ||
}; | ||
} | ||
|
||
export function validate(form) { | ||
return { | ||
type: VALIDATE, | ||
form: form | ||
}; | ||
} | ||
|
||
export function reset(form) { | ||
return { | ||
type: RESET, | ||
form: form | ||
}; | ||
} |
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,67 @@ | ||
import { CHANGE, VALIDATE, RESET } from './actionTypes'; | ||
|
||
/** | ||
* Creates a state structure like: | ||
* { | ||
* data: { | ||
* field1: 'value1', | ||
* field2: 'value2' | ||
* }, | ||
* errors: { | ||
* field1: 'error for field1', | ||
* field2: 'error for field2' | ||
* }, | ||
* visited: { | ||
* field1: true, | ||
* field2: false | ||
* } | ||
* } | ||
* | ||
* A field has been "visited" if its value has been updated since the creation of the reducer. | ||
* | ||
* @param name the name of the "state slice" where the data is stored | ||
* @param fields an array of field names, used when validating all values | ||
* @param validate a validation function that takes all the data and returns all the errors | ||
* @param initialData initial data to populate the state with | ||
* @returns {Function} a form reducer | ||
*/ | ||
export default function createFormReducer(name, fields, validate = () => {}, initialData = {}) { | ||
return (state = {data: initialData, errors: {}, visited: {}}, action = {}) => { | ||
if (action.form !== name) { | ||
return state; | ||
} | ||
switch (action.type) { | ||
case CHANGE: | ||
const data = { | ||
...state.data, | ||
[action.field]: action.value | ||
}; | ||
return { | ||
...state, | ||
data: data, | ||
errors: validate(data), | ||
visited: { | ||
...state.visited, | ||
[action.field]: true | ||
} | ||
}; | ||
case VALIDATE: | ||
const errors = validate(state.data); | ||
const visited = state.visited; | ||
fields.forEach(key => visited[key] = true); // mark all as visited | ||
return { | ||
...state, | ||
errors: errors, | ||
visited: visited | ||
}; | ||
case RESET: | ||
return { | ||
data: initialData, | ||
errors: {}, | ||
visited: {} | ||
}; | ||
default: | ||
return state; | ||
} | ||
}; | ||
} |
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,7 @@ | ||
import createFormReducer from './createFormReducer'; | ||
import reduxForm from './reduxForm'; | ||
|
||
export default reduxForm; | ||
export { | ||
createFormReducer | ||
}; |
Oops, something went wrong.