Skip to content

Instantly share code, notes, and snippets.

@shinaisan
Last active January 16, 2023 16:22
Show Gist options
  • Save shinaisan/0ad6d8664486fa3d0984f8e7b534171d to your computer and use it in GitHub Desktop.
Save shinaisan/0ad6d8664486fa3d0984f8e7b534171d to your computer and use it in GitHub Desktop.
Redux Form - Material UI Example
import React from 'react';
import MaterialUiForm from './MaterialUiForm';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import reducer from './reducer';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
const store = createStore(reducer);
class App extends React.Component {
constructor(props) {
super(props);
this.state = {debug: ''};
}
handleSubmit(values) {
const self = this;
self.setState({debug: JSON.stringify(values)});
}
render() {
const onSubmit = this.handleSubmit.bind(this);
return (
<Provider store={store}>
<MuiThemeProvider muiTheme={getMuiTheme()}>
<div>
<MaterialUiForm onSubmit={onSubmit} />
<div>
<pre>{this.state.debug}</pre>
</div>
</div>
</MuiThemeProvider>
</Provider>
);
}
}
export default App;
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
const asyncValidate = (values /*, dispatch */) => {
return sleep(1000).then(() => {
// simulate server latency
if (['[email protected]', '[email protected]'].includes(values.email)) {
// eslint-disable-next-line no-throw-literal
throw { email: 'Email already Exists' }
}
})
}
export default asyncValidate
#!/bin/bash
NAME=redux-form-material-ui
echo -n "This script runs create-react-app $NAME. Proceed? (Y/N) "
read YN
if [ x$YN != xY ]
then
echo "Bye."
exit
fi
# Delete this line only if you are sure what is done from this line on.
exit
create-react-app $NAME
cd $NAME
cp -v ../package.json .
cd src
rm -f App.* logo.svg
cp -v ../../*.js .
cd ..
yarn install
echo 'To launch the dev server, run `yarn run start`.'
import React from 'react'
import { Field, reduxForm } from 'redux-form'
import TextField from 'material-ui/TextField'
import { RadioButton, RadioButtonGroup } from 'material-ui/RadioButton'
import Checkbox from 'material-ui/Checkbox'
import SelectField from 'material-ui/SelectField'
import MenuItem from 'material-ui/MenuItem'
import asyncValidate from './asyncValidate'
const validate = values => {
const errors = {}
const requiredFields = [
'firstName',
'lastName',
'email',
'favoriteColor',
'notes'
]
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 renderTextField = ({
input,
label,
meta: { touched, error },
...custom
}) => (
<TextField
hintText={label}
floatingLabelText={label}
errorText={touched && error}
{...input}
{...custom}
/>
)
const renderCheckbox = ({ input, label }) => (
<Checkbox
label={label}
checked={input.value ? true : false}
onCheck={input.onChange}
/>
)
const renderRadioGroup = ({ input, ...rest }) => (
<RadioButtonGroup
{...input}
{...rest}
valueSelected={input.value}
onChange={(event, value) => input.onChange(value)}
/>
)
const renderSelectField = ({
input,
label,
meta: { touched, error },
children,
...custom
}) => (
<SelectField
floatingLabelText={label}
errorText={touched && error}
{...input}
onChange={(event, index, value) => input.onChange(value)}
children={children}
{...custom}
/>
)
const MaterialUiForm = props => {
const { handleSubmit, pristine, reset, submitting } = props
return (
<form onSubmit={handleSubmit}>
<div>
<Field
name="firstName"
component={renderTextField}
label="First Name"
/>
</div>
<div>
<Field name="lastName" component={renderTextField} label="Last Name" />
</div>
<div>
<Field name="email" component={renderTextField} label="Email" />
</div>
<div>
<Field name="sex" component={renderRadioGroup}>
<RadioButton value="male" label="male" />
<RadioButton value="female" label="female" />
</Field>
</div>
<div>
<Field
name="favoriteColor"
component={renderSelectField}
label="Favorite Color"
>
<MenuItem value="ff0000" primaryText="Red" />
<MenuItem value="00ff00" primaryText="Green" />
<MenuItem value="0000ff" primaryText="Blue" />
</Field>
</div>
<div>
<Field name="employed" component={renderCheckbox} label="Employed" />
</div>
<div>
<Field
name="notes"
component={renderTextField}
label="Notes"
multiLine={true}
rows={2}
/>
</div>
<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: 'MaterialUiForm', // a unique identifier for this form
validate,
asyncValidate
})(MaterialUiForm)
{
"name": "redux-form-selecting-form-values",
"version": "0.1.0",
"private": true,
"dependencies": {
"bootstrap": "^3.3.7",
"immutable": "^3.8.2",
"material-ui": "^0.19.4",
"react": "^16.0.0",
"react-bootstrap": "^0.31.5",
"react-dom": "^16.0.0",
"react-redux": "^5.0.6",
"redux": "^3.7.2",
"redux-form": "^7.1.2",
"redux-immutablejs": "^0.0.8"
},
"devDependencies": {
"react-scripts": "1.0.14"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
import { combineReducers } from 'redux';
import { reducer as formReducer } from 'redux-form';
const rootReducer = combineReducers({
form: formReducer
});
export default rootReducer;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment