Home > Blockchain >  Iterating over data to display inputs renders data multiple times
Iterating over data to display inputs renders data multiple times

Time:02-07

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>
  );
};
  •  Tags:  
  • Related