I am trying to create a custom component that iterates over an array of data and display for each item an input field type radio with its according label, it works but for some reason the data is displayed three times, instead of just once for each field and I cant figure out why, I just want to render just three inputs, why does this behavior occur, am I missing something? Here is my code:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Tooltip } from '@progress/kendo-react-tooltip';
import { Form, Field, FormElement } from '@progress/kendo-react-form';
import { RadioGroup, RadioButton } from '@progress/kendo-react-inputs';
import { Error } from '@progress/kendo-react-labels';
import { Input } from '@progress/kendo-react-inputs';
const emailRegex = new RegExp(/\S @\S \.\S /);
const data = [
{
label: 'Female',
value: 'female',
},
{
label: 'Male',
value: 'male',
},
{
label: 'Other',
value: 'other',
},
];
const emailValidator = (value) =>
emailRegex.test(value) ? '' : 'Please enter a valid email.';
const EmailInput = (fieldRenderProps) => {
const { validationMessage, visited, ...others } = fieldRenderProps;
return (
<div>
<Input {...others} />
{visited && validationMessage && <Error>{validationMessage}</Error>}
</div>
);
};
const Component = () => {
return (
<>
{data.map((item, index) => {
return (
<p>
<input
name="group1"
type="radio"
value={item.value}
label={item.label}
key={index}
/>
<label>{item.label}</label>
</p>
);
})}
</>
);
};
const App = () => {
const handleSubmit = (dataItem) => alert(JSON.stringify(dataItem, null, 2));
const tooltip = React.useRef(null);
return (
<Form
onSubmit={handleSubmit}
render={(formRenderProps) => (
<FormElement
style={{
maxWidth: 650,
}}
>
<fieldset className={'k-form-fieldset'}>
<legend className={'k-form-legend'}>
Please fill in the fields:
</legend>
<div className="mb-3">
<Field
name={'firstName'}
component={Input}
label={'First name'}
/>
</div>
<div className="mb-3">
<Field name={'lastName'} component={Input} label={'Last name'} />
</div>
<div className="mb-3">
<Field
name={'email'}
type={'email'}
component={EmailInput}
label={'Email'}
validator={emailValidator}
/>
</div>
</fieldset>
<div
onm ouseOver={(event) =>
tooltip.current && tooltip.current.handleMouseOver(event)
}
onm ouseOut={(event) =>
tooltip.current && tooltip.current.handleMouseOut(event)
}
>
<RadioGroup data={data} item={Component} />
<Tooltip
ref={tooltip}
anchorElement="target"
position="right"
openDelay={300}
parentTitle={true}
/>
</div>
<div className="k-form-buttons">
<button
type={'submit'}
className="k-button k-button-md k-rounded-md k-button-solid k-button-solid-base"
disabled={!formRenderProps.allowSubmit}
>
Submit
</button>
</div>
</FormElement>
)}
/>
);
};
ReactDOM.render(<App />, document.querySelector('my-app'));
and here is an example:
https://stackblitz.com/edit/react-rfb1ux-jpqvwy?file=app/main.jsx
CodePudding user response:
<RadioGroup data={[1]} item={Component} />
RadioGroup assumes that Component element is to be rendered over data array ... so it renders like this -->
data.map(val=><Component />)
here size of data array is 3 .
or
<Component />
CodePudding user response:
Radio Group will do the mapping for you. Try changing Component to:
const Component = (props) => {
return (
<p>
<input
name="group1"
type="radio"
value={props.children.props.value}
label={props.children.props.label}
key={props.children.props.label}
/>
<label>{props.children.props.label}</label>
</p>
);
};
This will then map out the items for you.
CodePudding user response:
seems like this works,
const Component = ({ children: { props } }) => {
const { value, label } = { ...props };
return (
<p>
<input name="group1" type="radio" value={value} label={label} />
<label>{label}</label>
</p>
);
};
