【问题标题】:Typescipt :typing the props passed by a wrapper component in ReactTypescript : 输入 React 中包装组件传递的 props
【发布时间】:2020-10-07 00:33:11
【问题描述】:

我有一个包装组件 A,它可以像这样向子组件添加道具

interface AProps {
   fooProp: string
}

const A : FunctionComponent<AProps> = (props)=>{
   const [someState, setSomeState] = useState("");//local state i want to pass to children
   const {children} = props;

   //...some other code setting someState

   // type guard making the compiler happy
   if (!React.isValidElement(children){
      return <></>
   }

   return (
     <>
         React.cloneElement(React.Children.only(children, {someState})
     </>
   )
};

现在我想将它与需要像这样的 someState:string 道具的组件 X 一起使用


<A fooProp="foobar">
   <X/>
</A

但是 Typescript 抱怨 X 没有提供所需的 someState 属性; 我如何让他知道组件 A 能够将 someState 道具传递给它的孩子?

【问题讨论】:

    标签: reactjs typescript


    【解决方案1】:

    只需将 prop 声明为可选:

        interface XProps {
            someState?: string;
        }
    
        class X extends React.Component<XProps> { ... }
    

    编辑

    也许更好的方法是 HOC(高阶组件),不需要React.cloneElement

    interface AProps {
       fooProp: string
    }
    interface XProps {
       someState: string;
    }
    
    function withSomeState(X: React.Component<XProps>) {
        const A: FunctionComponent<AProps> = (props) => {
           const [someState, setSomeState] = useState("");//local state i want to pass to children
    
           //...some other code setting someState
    
           // type guard making the compiler happy
           if (!React.isValidElement(X){
              return <></>
           }
    
           return (
             <X {someState} />
           );
        }
        return A;
    }
    
    const A = withSomeState(X);
    
    <A fooProp="foobar" />
    

    【讨论】:

    • 谢谢,但这更像是一种解决方法,而不是真正的解决方案(通过检查)。您认为没有其他解决方案吗?
    • 感谢您的 HOC 建议。我想知道这两种方法之间的真正区别是什么,因为“从美学上讲”父/子方式似乎更优雅,但从 Typescript 的角度来看,HOC 更有意义。
    • @Vincent J 是的,HOC 的主要好处在于 TypeScript。被包装组件的类型在编译时就很清楚了,而如果在另一种方法中作为子项传递,则直到运行时才知道,因此本质上更具动态性,这是 TypeScript 不喜欢的。
    • 我想到了一些东西。当使用包装器组件时,AFAIK 引擎盖下 JSX 使用内部(子)组件函数的结果作为参数与外部组件函数一起转译。所以内部组件在外部组件之前执行。因此,第一次呈现这三个时,内部函数执行时外部函数“状态”尚不可用,因此您将道具标记为可选的第一个建议是包装问题的正确答案。我的理解正确吗?
    • @VincentJ 外部和内部组件可以通过 HOC 进行通信。使用传递给 HOC 构造函数的第二个参数来传递要共享的数据。您甚至可以使用函数进行更灵活的通信,如 ReactJS 文档所示。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-24
    • 2018-12-27
    • 1970-01-01
    • 1970-01-01
    • 2016-10-28
    • 2017-11-17
    相关资源
    最近更新 更多