首页 > 解决方案 > 如何将道具传递给我们还不知道所需类型的 React 子组件

问题描述

是否可以将道具传递给我们还不知道所需类型的子组件?像这样的东西:

interface CardProps<T> {
  set: SetProps<T>;
  setSet: Dispatch<SetStateAction<SetProps<T>>>;
  children: ReactNode;
}

const RenderCards = <T extends object>({ set, setSet, children }: CardProps<T>) => (
  <>
    {set &&
      set.data &&
      set.data.map((item: T, idx: number) => (
        <SwipeBox
          key={idx}
          state={{ set, setSet }}
        >
          <MovieCard movie={item as MovieType} /> // This is too specific, want to delete.
          {children ...props} // This is flexible, but wrong.
        </SwipeBox>
      ))}
  </>
);

到目前为止,我已经提出了 Context API 作为一个可行的解决方案。它肯定比 Redux 少样板,但是,有没有更简单的方法?

标签: reactjstypescript

解决方案


我猜测您的意图,但我将其解释为:

  • 您希望支持为不同T类型渲染不同类型的卡片。
  • 您想通过某些道具传递给每张卡片。

我想出了一个基于渲染道具模式的解决方案。我们现在有两个泛型——T它仍然是项目类型,Extra另一个是我们传递的道具。

每张单独的卡片都会收到物品的属性作为道具,所有Extra道具,setsetSet(不确定最后两个是否真的需要)。

卡片组需要set, setSet,Extra道具和Render单个卡片的组件。

import React, { Dispatch, SetStateAction, ComponentType, useState } from "react";

interface SetProps<T> {
  data: T[];
}

interface CardProps<T> {
  set: SetProps<T>;
  setSet: Dispatch<SetStateAction<SetProps<T>>>;
}

type CardGroupProps<T, Extra = {}> = Extra &
  CardProps<T> & {
    Render: ComponentType<T & Extra & CardProps<T>>;
  };

const CardGroup = <T extends object, Extra extends object>(
   {set, setSet, Render, ...extra}: CardGroupProps<T, Extra>
) => (
  <>
    {set.data.map((item: T, idx: number) => (
      <SwipeBox 
        key={idx} 
        state={{ set, setSet }}
      >
        <Render 
           set={set} 
           setSet={setSet} 
           {...(extra as Extra)} 
           {...item} 
        />
      </SwipeBox>
    ))}
  </>
);

这是一个显示用法的愚蠢示例。在这里,我们的RenderMovieCard组件需要Movieitem 和colorprop。如果您尝试在不传递此必需属性的情况下调用CardGroupwith,您将收到错误消息。Render={RenderMovieCard}color


interface Movie {
  title: string;
}

const RenderMovieCard = ({ title, color }: Movie & { color: string }) => (
  <div style={{ color }}>{title}</div>
);

export default () => {
  const [movies, setMovies] = useState<SetProps<Movie>>({
    data: [{ title: "Jaws" }, { title: "Star Wars" }]
  });

  return (
    <CardGroup
      set={movies}
      setSet={setMovies}
      Render={RenderMovieCard}
      color="red"
    />
  );
};

代码沙箱


推荐阅读