killed the "adapter" API. it was dumb.

This commit is contained in:
Erik Rasmussen
2016-05-30 19:44:42 +02:00
parent 5998539498
commit a43233e365
15 changed files with 2 additions and 490 deletions

View File

@@ -26,15 +26,6 @@ or passed in as props to your component at runtime.**
### Optional
#### -`adapter : (component:String, props:Object) => ReactElement` [optional]
> An adapter function that will render a component based on a string component type and the props
given to a `Field`. **Remember that all you really need to hook up to your custom component is
`value` and `onChange`.** An example can be found in the
[`redux-form-material-ui`](https://github.com/erikras/redux-form-material-ui) library.
Defaults to `[]`.
> See [Asynchronous Blur Validation Example](../../examples/asyncValidation) for more
details.

View File

@@ -64,11 +64,6 @@ open [`localhost:3030`](http://localhost:3030) in your browser.
---
### [Adapter](adapter)
> How to use the built-in "adapter" API.
---
### [Material-UI Examples](material-ui)
> Contains multiple Material-UI examples

View File

@@ -1,3 +0,0 @@
{
"presets": ["react", "es2015", "stage-2"]
}

View File

@@ -1,10 +0,0 @@
# Simple Material UI Form Example
## To run locally
```
npm install
npm start
```
Then open [`http://localhost:3030/`](http://localhost:3030/).

View File

@@ -1,27 +0,0 @@
var path = require('path');
var express = require('express');
var webpack = require('webpack');
var config = require('./webpack.config.dev');
var app = express();
var compiler = webpack(config);
app.use(require('webpack-dev-middleware')(compiler, {
noInfo: true,
publicPath: config.output.publicPath
}));
app.use(require('webpack-hot-middleware')(compiler));
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname, 'index.html'));
});
app.listen(3030, 'localhost', function(err) {
if (err) {
console.log(err);
return;
}
console.log('Listening at http://localhost:3030');
});

View File

@@ -1,90 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charSet="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
<title>Redux Form</title>
<link href="http://redux-form.com/6.0.0-alpha.14/bundle.css"
media="screen, projection"
rel="stylesheet" type="text/css"/>
<link href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.min.css"
media="screen, projection" rel="stylesheet" type="text/css"/>
<style type="text/css">
/*This CSS has been tweaked from root site
to match with material-ui*/
form > div > div > div {
padding: 0px;
border: none;
}
</style>
<meta itemprop="name" content="Redux Form"/>
<meta property="og:type" content="website"/>
<meta property="og:title" content="Redux Form"/>
<meta property="og:site_name" content="Redux Form"/>
<meta property="og:description"
content="The best way to manage your form state in Redux."/>
<meta property="og:image" content="logo.png"/>
<meta property="twitter:site" content="@erikras"/>
<meta property="twitter:creator" content="@erikras"/>
</head>
<body>
<div id="content">
<style type="text/css" scoped>
.loader {
margin: 10% auto;
font-size: 10px;
position: relative;
text-indent: -9999em;
border-top: 1.1em solid rgba(100, 100, 100, 0.2);
border-right: 1.1em solid rgba(100, 100, 100, 0.2);
border-bottom: 1.1em solid rgba(100, 100, 100, 0.2);
border-left: 1.1em solid grey;
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
transform: translateZ(0);
-webkit-animation: load8 1.1s infinite linear;
animation: load8 1.1s infinite linear;
}
.loader,
.loader:after {
border-radius: 50%;
width: 10em;
height: 10em;
}
@-webkit-keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
</style>
<div class="loader">Loading...</div>
</div>
<script type="text/javascript" src="dist/bundle.js"></script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-69298417-1', 'auto');
ga('send', 'pageview');
</script>
</body>
</html>

View File

@@ -1,49 +0,0 @@
{
"private": true,
"scripts": {
"clean": "rimraf dist",
"build:webpack": "cross-env NODE_ENV=production webpack --config webpack.config.prod.js",
"build": "npm run clean && npm run build:webpack",
"lint": "eslint src",
"start": "node devServer.js",
"prepublish": "npm run lint && npm run build"
},
"dependencies": {
"babel-polyfill": "^6.6.1",
"html-loader": "^0.4.3",
"json-loader": "^0.5.4",
"markdown-loader": "^0.1.7",
"material-ui": "^0.15.0",
"raw-loader": "^0.5.1",
"react": "^15.0.0-rc.2",
"react-dom": "^15.0.0-rc.2",
"react-redux": "^4.4.1",
"react-tap-event-plugin": "^1.0.0",
"redux": "^3.3.1",
"redux-form": "file:../../",
"redux-form-material-ui": "^1.0.0",
"redux-form-website-template": "0.0.30"
},
"devDependencies": {
"babel-core": "^6.3.15",
"babel-eslint": "^5.0.0-beta4",
"babel-loader": "^6.2.0",
"babel-preset-es2015": "^6.3.13",
"babel-preset-react": "^6.3.13",
"babel-preset-stage-2": "^6.1.18",
"cross-env": "^1.0.7",
"eslint": "^1.6.0",
"eslint-config-rackt": "^1.1.1",
"eslint-loader": "^1.3.0",
"eslint-plugin-babel": "^3.0.0",
"eslint-plugin-react": "^3.11.3",
"eventsource-polyfill": "^0.9.6",
"express": "^4.13.3",
"extract-text-webpack-plugin": "^1.0.1",
"redbox-react": "^1.2.2",
"rimraf": "^2.4.3",
"webpack": "^1.12.9",
"webpack-dev-middleware": "^1.4.0",
"webpack-hot-middleware": "^2.6.0"
}
}

View File

@@ -1,20 +0,0 @@
# Adapter Example
The "adapter" API in `redux-form` provides an easy way to provide shortcuts to certain commonly
used ways of rendering inputs. An "adapter" function, in `redux-form`, takes a string that
corresponds to the `component` prop on the `Field` component, and the props that `redux-form`
would normally give to the `component`, and gives back a React element. To write that more
succinctly in code:
```js
const adapter = (componentName, props) => <MyCustomComponent {...props}/>
```
The adapter API is provided for convenience only, as you could always pass predefined components
or stateless function components to your `component` prop. The primary motivation for the adapter
interface is to allow third party input libraries to provide easy ways to adapt popular third
party input widgets to `redux-form`. e.g.
[`redux-form-material-ui`](https://github.com/erikras/redux-form-material-ui).
The example below is fairly contrived, and is meant only to demonstrate how it works and the kind
of flexibility the adapter API provides. It should not necessarily be copied.

View File

@@ -1,39 +0,0 @@
import React from 'react'
import { Field, reduxForm } from 'redux-form'
import adapter from './adapter'
const validate = values => {
const errors = {}
const requiredFields = [ 'username', 'password', 'email', 'age' ]
requiredFields.forEach(field => {
if (!values[ field ]) {
errors[ field ] = 'Required'
}
})
if (values.email && !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
errors.email = 'Invalid email address'
}
return errors
}
const AdapterForm = props => {
const { handleSubmit, pristine, reset, submitting } = props
return (
<form onSubmit={handleSubmit}>
<Field name="username" label="Username" component="myCustomText"/>
<Field name="password" label="Password" component="myCustomPassword"/>
<Field name="email" label="Email" component="myCustomEmail"/>
<Field name="age" label="Age" component="myCustomNumber"/>
<div>
<button type="submit" disabled={pristine || submitting}>Submit</button>
<button type="button" disabled={pristine || submitting} onClick={reset}>Clear Values</button>
</div>
</form>
)
}
export default reduxForm({
form: 'adapterExample', // a unique identifier for this form
adapter,
validate
})(AdapterForm)

View File

@@ -1,43 +0,0 @@
import React from 'react'
const FieldWrapper = ({ touched, error, children, label }) =>
<div>
<label>{label}</label>
<div>
{children}
{touched && error && <span>{error}</span>}
</div>
</div>
const components = {
myCustomText: props =>
<FieldWrapper {...props}>
<input type="text" {...props} placeholder={props.label}/>
</FieldWrapper>,
myCustomEmail: props =>
<FieldWrapper {...props}>
<input type="email" {...props} placeholder={props.label}/>
</FieldWrapper>,
myCustomPassword: props =>
<FieldWrapper {...props}>
<input type="password" {...props} placeholder={props.label}/>
</FieldWrapper>,
myCustomNumber: props =>
<FieldWrapper {...props}>
<input type="number" {...props} placeholder={props.label}/>
</FieldWrapper>
}
const adapter = (key, props) => {
const component = components[ key ]
if (component) {
return component(props)
}
}
export default adapter

View File

@@ -1,95 +0,0 @@
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import { createStore, combineReducers } from 'redux'
import { reducer as reduxFormReducer } from 'redux-form'
import {
App,
Code,
Markdown,
Values,
generateExampleBreadcrumbs
} from 'redux-form-website-template'
const dest = document.getElementById('content')
const reducer = combineReducers({
form: reduxFormReducer // mounted under "form"
})
const store =
(window.devToolsExtension ? window.devToolsExtension()(createStore) : createStore)(reducer)
const showResults = values =>
new Promise(resolve => {
setTimeout(() => { // simulate server latency
window.alert(`You submitted:\n\n${JSON.stringify(values, null, 2)}`)
resolve()
}, 500)
})
let render = () => {
const AdapterForm = require('./AdapterForm').default
const readme = require('./Adapter.md')
const raw = require('!!raw!./AdapterForm')
const adapterRaw = require('!!raw!./adapter')
ReactDOM.render(
<Provider store={store}>
<App
/**
* This <App/> component only provides the site wrapper.
* Remove it on your dev server if you wish. It will not affect the functionality.
*/
version="6.0.0-alpha.14"
path="/examples/adapter/"
breadcrumbs={generateExampleBreadcrumbs('adapter', 'Adapter Example', '6.0.0-alpha.14')}>
<Markdown content={readme}/>
<h2>Form</h2>
<AdapterForm onSubmit={showResults}/>
<Values form="adapterExample"/>
<h2>Code</h2>
<h4>adapter.js</h4>
<Code source={adapterRaw}/>
<h4>AdapterForm.js</h4>
<Code source={raw}/>
</App>
</Provider>,
dest
)
}
if (module.hot) {
// Support hot reloading of components
// and display an overlay for runtime errors
const renderApp = render
const renderError = (error) => {
const RedBox = require('redbox-react')
ReactDOM.render(
<RedBox error={error} className="redbox"/>,
dest
)
}
render = () => {
try {
renderApp()
} catch (error) {
renderError(error)
}
}
const rerender = () => {
setTimeout(render)
}
module.hot.accept('./AdapterForm', rerender)
module.hot.accept('./Adapter.md', rerender)
module.hot.accept('!!raw!./AdapterForm', rerender)
module.hot.accept('!!raw!./adapter', rerender)
}
render()

View File

@@ -1,45 +0,0 @@
var path = require('path');
var webpack = require('webpack');
module.exports = {
devtool: 'eval',
entry: [
'babel-polyfill',
'eventsource-polyfill', // necessary for hot reloading with IE
'webpack-hot-middleware/client',
'./src/index'
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: '/dist/'
},
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin()
],
resolve: {
modulesDirectories: [
'src',
'node_modules'
],
extensions: [ '', '.json', '.js' ]
},
module: {
loaders: [
{
test: /\.jsx?/,
loaders: [ 'babel', 'eslint' ],
include: path.join(__dirname, 'src')
},
{
test: /\.json$/,
loader: 'json-loader'
},
{
test: /\.md/,
loaders: [ "html-loader", "markdown-loader" ]
}
]
}
};

View File

@@ -1,52 +0,0 @@
var path = require('path');
var webpack = require('webpack');
module.exports = {
devtool: 'source-map',
entry: [
'babel-polyfill',
'./src/index'
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: '/dist/'
},
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production')
}
}),
new webpack.optimize.UglifyJsPlugin({
compressor: {
warnings: false
}
})
],
resolve: {
modulesDirectories: [
'src',
'node_modules'
],
extensions: [ '', '.json', '.js' ]
},
module: {
loaders: [
{
test: /\.js$/,
loaders: [ 'babel' ],
include: path.join(__dirname, 'src')
},
{
test: /\.json$/,
loader: 'json-loader'
},
{
test: /\.md/,
loaders: [ "html-loader", "markdown-loader" ]
}
]
}
};

View File

@@ -19,8 +19,8 @@ Notice that we define simple functions, like `renderTextField`, `renderCheckbox`
`renderSelectField` to form a bridge between `redux-form` and the Material UI input components.
You would only need to define these in one place in your application and reuse them in each form.
In fact, we recommend using an adapter. For Material UI, an adapter has already been made for
you: [`redux-form-material-ui`](https://github.com/erikras/redux-form-material-ui).
For Material UI, `@erikras` has published a set of wrapper components to use Material UI:
[`redux-form-material-ui`](https://github.com/erikras/redux-form-material-ui).
### How to use async validation in form:

View File

@@ -274,7 +274,6 @@ const createReduxForm =
_reduxForm: PropTypes.object.isRequired
}
Form.propTypes = {
adapter: PropTypes.func,
destroyOnUnmount: PropTypes.bool,
form: PropTypes.string.isRequired,
initialValues: PropTypes.object,