是否可以在容器组件的函数之间传递React组件作为参数

时间:2016-06-24 13:59:04

标签: reactjs

将子组件作为参数传递给父组件的函数并尝试渲染不起作用

//React Container Component
//Import Both Views and Render based on preference
import PosterView from "./PosterView"
import ListView from "./ListViewCard"

...

renderCardsBasedOnType(cardType){
  if(cardType === "poster"){
     return this.renderCards(PosterView)
  }else{
     return this.renderCards(ListViewCard)
  }
}
renderCards(component){
  let cards =  this.props.list.map(function(cardData){
     return <component data={cardData}/>
   })
  return cards
}
render(){
  let cards = this.renderCardsBasedOnType("poster")
  return <div>{cards}</div>
}
......

3 个答案:

答案 0 :(得分:26)

尝试使用Component代替component。 React需要一个用于jsx标记的upperCase:

renderCards(Component){
  let cards =  this.props.list.map(function(cardData){
     return <Component data={cardData}/>
   })
  return cards
}

答案 1 :(得分:0)

感谢达米安的回答,这是使用Typescript和React的相同答案。

取而代之的是没有包装的简单组件...

export const SiteMapContent: FunctionComponent = () => {
  return (
    <React.Fragment>
      <h1>Site Map</h1>
      <p>This will display the site map.</p>
    </React.Fragment>
  );
}

...您可以将组件传递到包装中以在此处呈现,就像这样...

const renderContent: FunctionComponent<FunctionComponent> = (Foo: FunctionComponent) => {
  return (
    <div className="foo">
      <Foo />
    </div>
  )
}

export const SiteMap: FunctionComponent = () => {
  return renderContentOne(SiteMapContent);
}

const SiteMapContent: FunctionComponent = () => {
  return (
    <React.Fragment>
      <h1>Site Map</h1>
      <p>This will display the site map.</p>
    </React.Fragment>
  );
}

同样,参数名称必须是大写字母,例如Foo不是foo

当然,与传递OP中所要求的传递组件不同的是,传递元素而不是传递组件(在这种情况下,参数名称不必为大写):

const renderContent: FunctionComponent<ReactElement> = (foo: ReactElement) => {
  return (
    <div className="foo">
      {foo}
    </div>
  )
}

export const SiteMap: FunctionComponent = () => {
  const foo: ReactElement = <SiteMapContent />;
  return renderContentOne(foo);
}

const SiteMapContent: FunctionComponent = () => {
  return (
    <React.Fragment>
      <h1>Site Map</h1>
      <p>This will display the site map.</p>
    </React.Fragment>
  );
}

答案 2 :(得分:0)

您可以使用 React.createElment(myLowerCasedComponent) - 我正在学习 Javascript 教程并即时移植到 TypeScript。在 TypeScript 中,我是这样工作的:

    // PrivateRoute.tsx
    type PropType = {
        component: React.ComponentType
    } & RouteProps
    
    // Component that wraps another component to produce a
    // component which only renders if the user is logged in. If not logged
    // in then the browser is redirected to the signin component.
    const PrivateRoute: React.FC<PropType> = ({ component, ...rest }) => {
        return (
            <Route
                {...rest}
                render={(props) =>
                    isAuth() ? (
                        React.createElement(component)
                    ) : (
                        <Redirect
                            to={{
                                pathname: '/signin',
                                state: { from: props.location }
                            }}
                        />
                    )
                }
            ></Route>
        )
    }
    
    export default PrivateRoute

这意味着我可以像这样调用我的包装器:

    class Routes extends React.Component {
        render(): React.ReactElement {
            return (
                <BrowserRouter>
                    <Switch>
                        <Route path="/signin" exact component={Signin} />
                        <Route path="/auth/activate/:token" exact component={Activate} />
                        <AdminRoute path="/admin" exact component={Admin} />
                        { /* here my param name is 'component' matching than
                             the other routes. Not 'Component=Private' (ugh) */ }
                        <PrivateRoute path="/private" exact component={Private} />
                    </Switch>
                </BrowserRouter>
            )
        }
    }
    
    export default Routes

这里我的 Private 组件是一个标准的基于 React 类的组件:

}

type ChangeHandler = (e: React.ChangeEvent<HTMLInputElement>) => void

class Private extends React.Component<PropType, StateType> {
    render(): JSX.Element {
        return (
            <Layout>
                <div className="col-md-6 offset-md-3">
                { /* stuff here... */ }
                </div>
            </Layout>
        )
    }
}