Búsqueda de sitios web

reactjs - ¿Cómo pasar props a {children} y usarlos?


Estoy tratando de hacer un elemento de entrada reutilizable en React. Versión de React: "react": "17.0.2"

Quiero pasar htmlFor en la etiqueta y usar el mismo en la propiedad id de los hijos. Así que estoy intentando pasar props a {children} en React. He intentado pasar props a partir de esta solución

      {React.cloneElement(children, { id: label })}

Mi componente que utiliza hijos.

import clsx from 'clsx';
import React from 'react';
import { FunctionComponent } from 'react'; // importing FunctionComponent

type FieldWrapperProps = {
  children: React.ReactNode;
  label: string;
  errorMessage?: string;
  className?: string;
};

export const FieldWrapper: FunctionComponent<FieldWrapperProps> = (props: FieldWrapperProps) => {
  const { children, label, errorMessage, className } = props;
  return (
    <div
      className={clsx('mt-6  flex flex-col justify-center tracking-wide align-middle', className)}
    >
      <label htmlFor={label} className="block text-gray-light text-base  font-bold mb-2 peer">
        {label}
      </label>
      {React.cloneElement(children, { id: label })}
      {/* {children} */}
      <p className="text-sm text-red-500 ">{errorMessage}</p>
    </div>
  );
};

Estoy usando este FieldWrapper en varios otros elementos del formulario de la siguiente manera.

import { UseFormRegisterReturn } from 'react-hook-form';

import { FieldWrapper } from './FieldWrapper';

type InputFieldProps = {
  label: string;
  type: string;
  registration?: UseFormRegisterReturn;
  error?: string;
  placeholderText?: string;
  className?: string;
};

export const InputField = (props: InputFieldProps) => {
  const { type, label, registration, error, placeholderText, className } = props;
  return (
    <FieldWrapper label={label} errorMessage={error} className={className}>
      <input
        type={type}
        className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
        id={label}
        placeholder={placeholderText}
        {...registration}
      />
    </FieldWrapper>
  );
};

También hay una advertencia de tipo.

Respuesta #1

Estás obteniendo este error de tipo porque React.cloneElement() requiere un Element para clonar; children no está garantizado que sea un elemento. Es un ReactNode, que es un alias de tipo que incluye undefined y null. Esos son tipos válidos para devolver desde un componente de React, pero no para pasar a cloneElement. Podrías hacer esto en su lugar:

children = React.Children.map(children, el => {
  return React.cloneElement(el, { id: label })
})

Esto te permitiría clonar cada elemento a su vez. Si solo esperas un único elemento, React.Children.only() puede usarse de manera similar

children = React.Children.only(children)
children = React.cloneElement(children)