ts react 怎样实现不用传参的高阶组件?

怎样实现像react-router-dom那样,使用withRouter()后不用传参的高阶组件?

import React from "react";
import {RouteComponentProps, withRouter} from "react-router-dom";


type Props = {
    data: number
}

//高阶组件
const HOC = <P extends Omit<Props, "data">>(WrappedComponent: React.ComponentType<P>) => {
    const dataFromContext = 123;//假设这是从context中获取的数据
    return (props: P) => {
        return (
            <div>
                <WrappedComponent data={dataFromContext} {...props}/>
            </div>
        )
    }
};

//-----------------

//使用高阶组件
const ComponentA = (props: Props) => {
    return (
        <div>Context Data: {props.data}</div>
    )
};

const A = HOC(ComponentA);

//-----------------

//使用react-router-dom的高阶组件
const ComponentB = (props: RouteComponentProps) => {
    return (
        <div>{props.location.pathname}</div>
    )
};

const B = withRouter(ComponentB);

//-----------------

export const TestPage = () => (
    <div>
        不需要传参的组件
        <A/>{/*报错,提示需要传参数 data */}
        <B/>{/*正常*/}
    </div>
);
阅读 2.6k
2 个回答

试试这个

type Props = {
  data: number;
};

//高阶组件
const HOC = <P extends Props>(
  WrappedComponent: React.FC<P>
): React.FC<Omit<P, "data">> => {
  const dataFromContext = 123; //假设这是从context中获取的数据
  return (props: P) => {
    return (
      <div>
        <WrappedComponent data={dataFromContext} {...props} />
      </div>
    );
  };
};

//-----------------

//使用高阶组件
const ComponentA: React.FC<Props> = (props) => {
  return <div>Context Data: {props.data}</div>;
};

const A = HOC(ComponentA);

//-----------------

//使用react-router-dom的高阶组件
const ComponentB = (props: RouteComponentProps) => {
  return <div>{props.location.pathname}</div>;
};

const B = withRouter(ComponentB);

//-----------------

export const TestPage = () => (
  <div>
    不需要传参的组件
    <A />
    {/*报错,提示需要传参数 data */}
    <B />
    {/*正常*/}
  </div>
);

磨叽磨叽终于解决了,感谢楼上的兄弟 @jsdeferred

import React from "react"

type TestProps = {
  data: number
}

// 传入组件的类型
type WrappedComponentType<P extends object> = React.ComponentType<P & TestProps>

function HOC<P extends object>(WrappedComponent: WrappedComponentType<P>) {
  const C = (props: P) => {
      const { ...rest } = props
      const ctxData: TestProps = { data: 123456 } // 假设从Context获取该值
      return <WrappedComponent {...rest} {...ctxData} /> // 该组件必须传入TestProps类型的参数
  }
  return C
}

function ComponentA(props: TestProps) {
  return (
      <div>该值从高阶组件中获取:{props.data}</div>
  )
}
const A = HOC(ComponentA)

export default function App() {
  return (
    <div className="App">
      <A />
      <h1>Hello CodeSandbox</h1>
      <h2>
        实现一个类似 react-router-dom
        <br/>
        使用 withRouter(Component) 后不需要传参的组件</h2>
    </div>
  );
}

在 codesandbox 中查看
这回vscode不报错,idea不报错。

React版本

"dependencies": {
    "@types/react": "^17.0.3",
    "@types/react-dom": "^17.0.3",
    "react": "^17.0.2",
    "react-dom": "^17.0.2"
  }
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题