I have a simple list where I'm displaying a looped Select using .map.
Everything is working fine, but the initial default value of each select is not what I have in my array list.
How do I set a defaultValue for each select in the list?
https://codesandbox.io/s/festive-robinson-847oj?file=/src/App.js:0-1435
import React, { useState } from "react";
import Select from "react-select";
function SelectItem(props) {
const [value, setValue] = React.useState(props.list[0]);
return (
<Select
options={props.list}
onChange={(newValue) => {
setValue(newValue);
props.onChange(newValue.value);
}}
value={value}
/>
);
}
export default () => {
const animationsList = [
{ value: "animation1", label: "Dance" },
{ value: "animation2", label: "Flip" },
{ value: "animation3", label: "Salsa" }
];
const reactList = [
{
id: "1",
animation: "animation1"
},
{
id: "2",
animation: "animation2"
},
{
id: "3",
animation: "animation3"
}
];
const [links, setLinks] = useState(reactList);
const onChange = (index, animation) => {
const cloneLinks = [...links];
cloneLinks[index].animation = animation;
setLinks(cloneLinks);
console.log(cloneLinks);
};
return (
<div>
<ul>
<div>
{links.map((url, indexurl) => (
<li key={url.id}>
<div>
<SelectItem
onChange={(animation) => onChange(indexurl, animation)}
list={animationsList}
defaultValue={url.animation.value}
/>
</div>
</li>
))}
</div>
</ul>
</div>
);
};
A new state in the SelectItem component is not needed.
The value or defaultValue must be an object from the list that is used for options.
Here's the updated CSB.
function SelectItem(props) {
return (
<Select
options={props.list}
onChange={(newValue) => {
props.onChange(newValue.value);
}}
value={props.value}
/>
);
}
export default () => {
const animationsList = [
{ value: "animation1", label: "Dance" },
{ value: "animation2", label: "Flip" },
{ value: "animation3", label: "Salsa" }
];
const reactList = [
{
id: "1",
animation: "animation1"
},
{
id: "2",
animation: "animation2"
},
{
id: "3",
animation: "animation3"
}
];
const [links, setLinks] = useState(reactList);
const onChange = (index, animation) => {
const cloneLinks = [...links];
cloneLinks[index].animation = animation;
setLinks(cloneLinks);
console.log(cloneLinks);
};
return (
<div>
<ul>
<div>
{links.map((url, indexurl) => (
<li key={url.id}>
<div>
<SelectItem
onChange={(animation) => onChange(indexurl, animation)}
list={animationsList}
value={animationsList.find(
(aL) => aL.value === url.animation
)}
/>
</div>
</li>
))}
</div>
</ul>
</div>
);
};
I am using the react-select library with a list of states, and then using that to hide/show my elements
The elements are showing when I select them from the list, but then don't hide when they're removed. Here is the code:
import React from 'react';
import Select from 'react-select';
const options = [
{ value: 'ny', label: 'NY' },
{ value: 'ca', label: 'California' },
{ value: 'ak', label: 'Arkansas' }
];
export default class HomePage extends React.Component {
constructor(props) {
super(props);
this.state = {}
}
handleChange = (selectedOption) => {
if (!selectedOption) {
this.setState({})
}
else {
const result = {}
selectedOption.map((option) => {
result[option.value] = true
})
this.setState(result)
}
}
render() {
return (
<div>
<Select
isMulti
onChange={this.handleChange}
options={options}
/>
{this.state.ny && (
<div>NY State Images</div>
)}
{this.state.ca && (
<div>CA State Images</div>
)}
{this.state.ak && (
<div>AK State Images</div>
)}
</div>
)
}
}
Something is strange with that React.Component.
Try to use functional component:
export default function HomePage() {
const [state, setState] = useState({});
const handleChange = selectedOption => {
console.log("CHANGE_HAPPEN: ", selectedOption);
if (!selectedOption) {
setState({});
} else {
const result = {};
selectedOption.forEach(option => {
result[option.value] = true;
});
console.log("RESULT: ", result);
setState(prev => result);
}
};
return (
<div>
<Select isMulti onChange={handleChange} options={options} />
{state.ny && <div>NY State Images</div>}
{state.ca && <div>CA State Images</div>}
{state.ak && <div>AK State Images</div>}
</div>
);
}
I've created this cool sandbox that utilises react-select and the creatable feature. It allows you to select from a prepopulated dropdown and at the same time create a custom option by typing into the select field. Once you have typed into the field your option becomes available in the select list.
I have added in options to be grouped - pre-existing fields are fine, but new options I would like to be grouped by a default value e.g. "new group".
Any help would be appreciated.
https://codesandbox.io/s/p5x7m478rm
import React from "react";
import { Field, reduxForm, FieldArray } 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";
import validate from "./validate";
import CreatableSelect from "react-select/lib/Creatable";
const CustomStyle = {
option: (base, state) => ({
...base,
display: "inline",
marginRight: "10px",
backgroundColor: state.isSelected ? "#00285C" : "#eee",
cursor: "pointer"
}),
menuList: () => ({
padding: 10,
display: "inline-flex"
}),
menu: () => ({
position: "relative"
})
};
const createOption = (label: string) => ({
label,
value: label.toLowerCase().replace(/\W/g, "")
});
const formatGroupLabel = data => (
<div>
<span>{data.label}</span>
</div>
);
class LastNameSelectInput extends React.Component {
constructor(props) {
super(props);
}
state = {
value: this.props.options[0].options,
options: this.props.options
};
handleCreate = input => (inputValue: any) => {
this.setState({ isLoading: true });
setTimeout(() => {
const { options, value } = this.state;
const newOption = createOption(inputValue);
this.setState({
isLoading: false,
options: [...options, newOption],
value: newOption,
formatGroupLabel: "new label"
});
input.onChange(newOption);
}, 1000);
};
isValidNewOption = (inputValue, selectValue, selectOptions) => {
if (
inputValue.trim().length === 0 ||
selectOptions.find(option => option.name === inputValue)
) {
return false;
}
return true;
};
render() {
const { input, options } = this.props;
return (
<div>
<style>
{`.react-select__dropdown-indicator,.react-select__indicator-separator {
display: none;
}`}
</style>
<CreatableSelect
classNamePrefix="react-select"
options={this.state.options}
menuIsOpen={true}
onChange={value => {
let newValue = input.onChange(value);
this.setState({ value: newValue });
}}
onBlur={() => input.onBlur(input.value)}
onCreateOption={this.handleCreate(input)}
value={this.state.value}
styles={CustomStyle}
isClearable
isValidNewOption={this.isValidNewOption}
formatGroupLabel={formatGroupLabel}
/>
</div>
);
}
}
const MaterialUiForm = props => {
const { handleSubmit, options, pristine, reset, submitting } = props;
return (
<form onSubmit={handleSubmit}>
<div>
<Field name="option" component={LastNameSelectInput} {...props} />
</div>
</form>
);
};
export default reduxForm({
form: "MaterialUiForm", // a unique identifier for this form
validate,
asyncValidate
})(MaterialUiForm);
To achieve your goal I have changed the function handleCreate you have provided and the options props. You can see a live example here.
In MaterialUiForm.js
handleCreate = input => (inputValue: any) => {
this.setState({ isLoading: true });
setTimeout(() => {
const { options } = this.state;
const newOption = createOption(inputValue);
options.map(option => {
if (option.label === "New group") {
return {
label: option.label,
options: option.options.push(newOption)
};
}
return option;
});
this.setState({
isLoading: false,
options: [...options],
value: newOption,
formatGroupLabel: "new label"
});
input.onChange(newOption);
}, 1000);
In index.js
<MaterialUiForm
onSubmit={showResults}
initialValues={{
option: colourOptions,
option: flavourOptions
}}
options={[
{
label: "New group",
options: []
},
{
label: "Colours",
options: colourOptions
},
{
label: "Flavours",
options: flavourOptions
}
]}
/>
There is different and probably smarter way to do it but the logic is the good one.
I have a component that renders three custom radio buttons. The user can either submit the selected or clear (unselect) them, leaving with no selected radio buttons.
I tried some options with comparing the filterResult to the data.value, but without success. Here's a simplified code:
// imports
...
type Props = {
filterConfig: PropTypes.object,
filterValue: Proptypes.string,
onFilterChange: PropTypes.func
}
class Filter extends React.Component {
this.props = Props
this.state = {
filterValue: this.props.filterValue,
}
handleChange = (e) => {
this.setState({ filterValue: e.target.value })
}
handleSubmit = () => {
this.props.onFilterChange(this.state.filterValue)
this.refs.filterContainer.close()
}
handleClear = () => {
this.setState({ filterValue: '' })
}
renderOptions = () => {
const { data, name } = this.props.filterConfig
const options = data.map(
(o, i) => (
<div className='custom-radio' key={i}>
<input
id={`${name}-${i}`}
name={name}
onChange={this.handleChange}
type='radio'
value={o.value}
/>
<label htmlFor={`${name}-${i}`}>
<span />
{o.label}
</label>
</div>
)
)
return (
<div>
{options}
</div>
)
}
renderPickerNavigation = () => {
return (
<div>
<a
href='javascript:void(0)'
onClick={this.handleClear}
>
Clear
</a>
<a
href='javascript:void(0)'
onClick={this.handleSubmit}
>
Done
</a>
</div>
)
}
render = () => {
return (
<FilterWrapper
ref='filterWrapper'
>
{this.renderOptions()}
{this.renderPickerNavigation()}
</FilterWrapper>
)
}
}
The data I'm passing in is:
const filters = [
{
data: [{
label: 'Label 1',
value: 1
}, {
label: 'Label 2',
value: 2
}, {
label: 'Label 3',
value: 3
}],
name: 'userFilter'
}
]
EDIT: The click event on the native radio input works fine, so no need to change that to be on the custom radio (the span element) or the label.
You should begin with having a state variable that stores which radio is currently selected. The initial value for this should be null (or some other falsy value) if you want none to be pre-selected.
The reset button should trigger a function which resets this state variable back to the initial value.
Take a look at this simple demo, using custom css radio buttons as you requested:
class MyApp extends React.Component {
constructor() {
super();
this.state = {
selectedRadio: null,
products: [{id: 1, name: "foo"}, {id: 2, name: "bar"}, {id: 3, name: "baz"}]
}
}
select = (id) => {
this.setState({selectedRadio: id});
}
reset = () => {
this.setState({selectedRadio: null});
}
render() {
return (
<div>
{this.state.products.map(
(item) => {
return (
<div key={item.id}>
<input type="radio" name="myRadio" checked={this.state.selectedRadio === item.id} />
<label onClick={this.select.bind(this, item.id)}>{item.name}<span /></label>
</div>
);
}
)}
<button onClick={this.reset}>Reset</button>
</div>
);
}
}
ReactDOM.render(<MyApp />, document.getElementById("app"));
div {
margin: 10px 0;
}
input[type="radio"] {
display: none;
}
input[type="radio"]+label span {
display: inline-block;
width: 14px;
height: 14px;
margin-left: 4px;
vertical-align: middle;
cursor: pointer;
border-radius: 34%;
}
input[type="radio"]+label span {
background-color: #333;
}
input[type="radio"]:checked+label span {
background-color: orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
Note: Since you are hiding the input element with css, you cannot have any listeners on it (e.g onChange or onClick). Instead, you should have onClick on the span that replaces it (see code below).
For a solution of how to reset all "traditional", non-css-only radio buttons, see the snippet below:
class MyApp extends React.Component {
constructor() {
super();
this.state = {
selectedRadio: null,
products: [{id: 1, name: "foo"}, {id: 2, name: "bar"}, {id: 3, name: "baz"}]
}
}
select = (id) => {
this.setState({selectedRadio: id});
}
reset = () => {
this.setState({selectedRadio: null});
}
render() {
return (
<div>
{this.state.products.map(
(item) => {
return (
<div key={item.id}>
<label>{item.name}</label>
<input type="radio" name="myRadio" onChange={this.select.bind(this, item.id)} checked={this.state.selectedRadio === item.id} />
</div>
);
}
)}
<button onClick={this.reset}>Reset</button>
</div>
);
}
}
ReactDOM.render(<MyApp />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
This example can help you https://codepen.io/evoyan/pen/vxGBOw
Code:
class Radio extends React.Component {
constructor(props) {
super(props);
this.state = {selected: false};
}
toggle() {
const {onChange} = this.context.radioGroup;
const selected = !this.state.selected;
this.setState({selected});
onChange(selected, this);
}
setSelected(selected) {
this.setState({selected});
}
render() {
let classname = this.state.selected ? 'active' : ''
return (
<button type="button" className={classname} onClick={this.toggle.bind(this)}>
{this.state.selected ? 'yes' : 'no'}
</button>
);
}
}
Radio.contextTypes = {
radioGroup: React.PropTypes.object
};
class RadioGroup extends React.Component {
constructor(props) {
super(props);
this.options = [];
}
getChildContext() {
const {name} = this.props;
return {radioGroup: {
name,
onChange: this.onChange.bind(this)
}};
}
onChange(selected, child) {
this.options.forEach(option => {
if (option !== child) {
option.setSelected(!selected);
}
});
}
render() {
let children = React.Children.map(this.props.children, child => {
return React.cloneElement(child, {
ref: (component => {this.options.push(component);})
});
});
return <div className="radio-group">{children}</div>;
}
}
RadioGroup.childContextTypes = {
radioGroup: React.PropTypes.object
};
class Application extends React.Component {
render() {
return (
<RadioGroup name="test">
<Radio value="1" />
<Radio value="2" />
<Radio value="3" />
</RadioGroup>
);
}
}
/*
* Render the above component into the div#app
*/
ReactDOM.render(<Application />, document.getElementById('app'));
So, I have a property (fields), within which I wish to change the value of an element (countries). Alerting the value of countries currently displays the value 2, but I want to change the value to 100, so that re-alerting fields.countries.value, after the change, displays the new value.
How do I do this?
import type { State } from '../../common/types';
import DynamicField from './DynamicField';
import R from 'ramda';
import React from 'react';
import buttonsMessages from '../../common/app/buttonsMessages';
import linksMessages from '../../common/app/linksMessages';
import { FormattedMessage } from 'react-intl';
import { ValidationError } from '../../common/lib/validation';
import { connect } from 'react-redux';
import { fields } from '../../common/lib/redux-fields';
import {
Block,
Box,
Button,
Checkbox,
FieldError,
Flex,
Form,
Heading,
Input,
PageHeader,
Pre,
Radio,
Select,
Space,
Title,
View,
} from '../app/components';
// The example of dynamically loaded editable data.
// cato.org/publications/commentary/key-concepts-libertarianism
const keyConceptsOfLibertarianism = [
'Individualism',
'Individual Rights',
'Spontaneous Order',
'The Rule of Law',
'Limited Government',
'Free Markets',
'The Virtue of Production',
'Natural Harmony of Interests',
'Peace',
].map((concept, index) => ({
id: index,
name: concept,
}));
// Proof of concept. Country list will be read from firebase
const countryArray = [
{ label: 'Select Country', value: 0 },
{ label: 'France', value: 2 },
{ label: 'England', value: 4 },
{ label: 'Swizterland', value: 8 },
{ label: 'Germany', value: 16 },
{ label: 'Lithuania', value: 32 },
{ label: 'Romania', value: 64 },
].map((countryName, index) => ({
id: index,
name: countryName,
}));
// Dynamically create select list
const countryOptions = [];
countryArray.map(countryItem =>
countryOptions.push({ label: countryItem.name.label, value: countryItem.name.value }),
);
// Proof of concept. Country list will be read from firebase
const cityArray = [
{ label: 'Select City', value: 0 },
{ label: 'London', value: 50 },
{ label: 'Paris', value: 75 },
].map((cityName, index) => ({
id: index,
name: cityName,
}));
// Dynamically create select list
const cityOptions = [];
cityArray.map(cityItem =>
cityOptions.push({ label: cityItem.name.label, value: cityItem.name.value }),
);
// Proof of concept. Country list will be read from firebase
const gymArray = [
{ label: 'Select Gym', value: 0 },
{ label: 'Virgin Sport', value: 23 },
{ label: 'Sports Direct', value: 45 },
].map((gymName, index) => ({
id: index,
name: gymName,
}));
// Dynamically create select list
const gymOptions = [];
gymArray.map(gymItem =>
gymOptions.push({ label: gymItem.name.label, value: gymItem.name.value }),
);
type LocalState = {
disabled: boolean,
error: ?Object,
submittedValues: ?Object,
};
class FieldsPage extends React.Component {
static propTypes = {
fields: React.PropTypes.object.isRequired,
dynamicFields: React.PropTypes.object,
// getCities: React.PropTypes.object,
};
state: LocalState = {
disabled: false,
error: null,
submittedValues: null,
};
onFormSubmit = () => {
const { dynamicFields, fields } = this.props;
const values = {
...fields.$values(),
concepts: {
...dynamicFields,
},
};
// This is just a demo. This code belongs to Redux action creator.
// Disable form.
this.setState({ disabled: true });
// Simulate async action.
setTimeout(() => {
this.setState({ disabled: false });
const isValid = values.name.trim();
if (!isValid) {
const error = new ValidationError('required', { prop: 'name' });
this.setState({ error, submittedValues: null });
return;
}
this.setState({ error: null, submittedValues: values });
fields.$reset();
}, 500);
};
handleSelectedCountryChange = () => {
// Pass in the selected country value to get associated cites
const { fields, getCities } = this.props;
getCities('country', fields.$values());
};
/*
handleSelectedCityChange = (event => {
// Pass in the selected city value to get associated gyms
this.setState({secondLevel: event.target.value});
});
*/
render() {
const { fields } = this.props;
const { disabled, error, submittedValues } = this.state;
return (
<View>
<Title message={linksMessages.fields} />
<PageHeader
description="New clients enter their gym details here."
heading="New user entry form."
/>
<Form onSubmit={this.onFormSubmit}>
<Input
{...fields.name}
aria-invalid={ValidationError.isInvalid(error, 'name')}
disabled={disabled}
label="Your Name"
maxLength={100}
type="text"
/>
<FieldError error={error} prop="name" />
<Heading alt>Key Concepts of Libertarianism</Heading>
<Block>
<Flex wrap>
{keyConceptsOfLibertarianism.map(item =>
<Box mr={1} key={item.id}>
<DynamicField
disabled={disabled}
item={item}
path={['fieldsPage', 'dynamic', item]}
/>
</Box>,
)}
</Flex>
</Block>
<Block>
<Checkbox
{...fields.isLibertarian}
checked={fields.isLibertarian.value}
disabled={disabled}
label="I'm libertarian"
/>
<Checkbox
{...fields.isAnarchist}
checked={fields.isAnarchist.value}
disabled={disabled}
label="I'm anarchist"
/>
</Block>
<Block>
<Flex>
<Radio
{...fields.gender}
checked={fields.gender.value === 'male'}
disabled={disabled}
label="Male"
value="male"
/>
<Space x={2} />
<Radio
{...fields.gender}
checked={fields.gender.value === 'female'}
disabled={disabled}
label="Female"
value="female"
/>
<Space x={2} />
<Radio
{...fields.gender}
checked={fields.gender.value === 'other'}
disabled={disabled}
label="Other"
value="other"
/>
</Flex>
</Block>
<Block>
<Select
{...fields.countries}
disabled={disabled}
label="Countries"
onChange={this.handleSelectedCountryChange}
options={countryOptions}
/>
</Block>
<Block>
<Select
{...fields.cities}
disabled={disabled}
label="Cities"
// onChange={this.handleSelectedCityChange}
options={cityOptions}
/>
</Block>
<Block>
<Select
{...fields.gyms}
disabled={disabled}
label="Gyms"
// onChange={this.handleSelectedCityChange}
options={gymOptions}
/>
</Block>
{/*
Why no multiple select? Because users are not familiar with that.
Use checkboxes or custom checkable dynamic fields instead.
*/}
<Button disabled={disabled} type="submit">
<FormattedMessage {...buttonsMessages.submit} />
</Button>
{submittedValues &&
<Pre>
{JSON.stringify(submittedValues, null, 2)}
</Pre>
}
</Form>
</View>
);
}
}
FieldsPage = fields({
path: 'fieldsPage',
fields: [
'countries',
'cities',
'gyms',
'gender',
'isAnarchist',
'isLibertarian',
'name',
],
getInitialState: () => ({
countries: '0',
cities: '0',
gyms: '0',
gender: 'male',
isAnarchist: false,
isLibertarian: false,
}),
})(FieldsPage);
export default connect(
(state: State) => ({
dynamicFields: R.path(['fieldsPage', 'dynamic'], state.fields),
}),
)(FieldsPage);
=====================================================================
fields.js
/* #flow weak */
import R from 'ramda';
import React from 'react';
import invariant from 'invariant';
import { resetFields, setField } from './actions';
type Path = string | Array<string> | (props: Object) => Array<string>;
type Options = {
path: Path,
fields: Array<string>,
getInitialState?: (props: Object) => Object,
};
const isReactNative =
typeof navigator === 'object' &&
navigator.product === 'ReactNative'; // eslint-disable-line no-undef
// Higher order component for huge fast dynamic deeply nested universal forms.
const fields = (options: Options) => (WrappedComponent) => {
const {
path = '',
fields = [],
getInitialState,
} = options;
invariant(Array.isArray(fields), 'Fields must be an array.');
invariant(
(typeof path === 'string') ||
(typeof path === 'function') ||
Array.isArray(path)
, 'Path must be a string, function, or an array.');
return class Fields extends React.Component {
static contextTypes = {
store: React.PropTypes.object, // Redux store.
};
static getNormalizePath(props) {
switch (typeof path) {
case 'function': return path(props);
case 'string': return [path];
default: return path;
}
}
static getFieldValue(field, model, initialState) {
if (model && {}.hasOwnProperty.call(model, field)) {
return model[field];
}
if (initialState && {}.hasOwnProperty.call(initialState, field)) {
return initialState[field];
}
return '';
}
static lazyJsonValuesOf(model, props) {
const initialState = getInitialState && getInitialState(props);
// http://www.devthought.com/2012/01/18/an-object-is-not-a-hash
return options.fields.reduce((fields, field) => ({
...fields,
[field]: Fields.getFieldValue(field, model, initialState),
}), Object.create(null));
}
static createFieldObject(field, onChange) {
return isReactNative ? {
onChangeText: (text) => {
onChange(field, text);
},
} : {
name: field,
onChange: (event) => {
// Some custom components like react-select pass the target directly.
const target = event.target || event;
const { type, checked, value } = target;
const isCheckbox = type && type.toLowerCase() === 'checkbox';
onChange(field, isCheckbox ? checked : value);
},
};
}
state = {
model: null,
};
fields: Object;
values: any;
unsubscribe: () => void;
onFieldChange = (field, value) => {
const normalizedPath = Fields.getNormalizePath(this.props).concat(field);
this.context.store.dispatch(setField(normalizedPath, value));
};
createFields() {
const formFields = options.fields.reduce((fields, field) => ({
...fields,
[field]: Fields.createFieldObject(field, this.onFieldChange),
}), {});
this.fields = {
...formFields,
$values: () => this.values,
$setValue: (field, value) => this.onFieldChange(field, value),
$reset: () => {
const normalizedPath = Fields.getNormalizePath(this.props);
this.context.store.dispatch(resetFields(normalizedPath));
},
};
}
getModelFromState() {
const normalizedPath = Fields.getNormalizePath(this.props);
return R.path(normalizedPath, this.context.store.getState().fields);
}
setModel(model) {
this.values = Fields.lazyJsonValuesOf(model, this.props);
options.fields.forEach((field) => {
this.fields[field].value = this.values[field];
});
this.fields = { ...this.fields }; // Ensure rerender for pure components.
this.setState({ model });
}
componentWillMount() {
this.createFields();
this.setModel(this.getModelFromState());
}
componentDidMount() {
const { store } = this.context;
this.unsubscribe = store.subscribe(() => {
const newModel = this.getModelFromState();
if (newModel === this.state.model) return;
this.setModel(newModel);
});
}
componentWillUnmount() {
this.unsubscribe();
}
render() {
return (
<WrappedComponent {...this.props} fields={this.fields} />
);
}
};
};
export default fields;