网站搜索

reactjs - 如何在 React Typescript 中绑定 match?


我有这段代码:

...
import { match, RouteComponentProps } from "react-router";
import * as H from 'history';

interface oneRoute {
    path: string;
    exact?: boolean;
    main: any;
}

interface ITestProps {
    id: string;
}

class Test extends React.Component<RouteComponentProps<ITestProps>, {}> {
    public render() {
        return <div>Hallow id:{this.props.match.params.id} -- {JSON.stringify(this.props.match)}</div>
    }
} 

export const routesData: oneRoute[] = [
    {
        path: '/',
        exact: true,
        main: (match: match<any>, location: H.Location, history: H.History) => <Home match={match} location={location} history={history} />
    },

    {
        path: '/test/:id',
        exact: false,
        main: (match: match<ITestProps>, location: H.Location, history: H.History) => <Test match={match} location={location} history={history} />
    }
]

export const routes = <Layout>
    {
    routesData.map((route, index) => {
        return <Route exact={route.exact} key={index} path={route.path} component={route.main} />;
    })
}    
</Layout>;

我在链接 "/test/12" 的测试中有一个错误。

未捕获的类型错误:无法读取未定义的属性 'id'。

如果我注释掉 this.props.match.params.id,JSON.stringify(this.props.match) 显示 "match":{"path":"/test/:id","url":"/test/12","isExact":true,"params":{"id":"12"}},所以是有 params.id 的。怎么会这样,以及如何解决获取 this.props.match.params.id 的问题?

答案#1

你在这里的设置方式是,你的组件 Test 会得到一个名为 match 的参数,它有一个名为 match 的 属性,这个属性包含你想要的实际对象(this.props.match.match.params.id)。

你告诉你的 Route 要渲染的 component 是:

(match: match<ITestProps>, location: H.Location, history: H.History) => <Test match={match} location={location} history={history} />

组件只会被调用一次参数,该参数是一个 props 对象。在运行时,这里的变量 match 并不是 match<ITestProps>,而是整个 RouteComponentProps 对象。

当设置 component={route.main} 时,Typescript 不会对此发出警告,因为 route.main 的类型是 any,所以默认认为它是兼容的。

在你的界面中更加具体:

interface oneRoute {
    path: string;
    exact?: boolean;
    main: React.ComponentType<RouteComponentProps<any>>;
}

你可以让 main 成为一个函数,该函数解构属性 match、location 和 history 并将它们传递给组件,但鉴于你没有更改任何属性,这实际上没有意义。main 可以直接就是组件本身。

export const routesData: oneRoute[] = [
    {
        path: '/',
        exact: true,
        main: Home,
    },
    {
        path: '/test/:id',
        exact: false,
        main: Test,
    }
]