首页 > 解决方案 > 我将如何在 Typescript 中创建反应路由器?

问题描述

在一个正常的反应项目中,我的路由器看起来像这样

我会将我的应用程序包装在一个 Component 中,然后我将拥有这个

<Switch>

<Route path="/login" render={(props) => <LoginPage login={this.login} authed={this.state.isAuthenticated} {...props} />} />
<Route path="/" render={(props) => this.props.history.push("/login")} />

</Switch>

但我不知道如何在 typescript 中模拟类似的东西。我目前有这个

const App: React.FunctionComponent = () => {
  return (
    <Router>
      <div className="main-content">
        <div>
          <Switch>
            <Route exactly component={Main} exact pattern="/" />
            <Route exactly component={Count} exact pattern="/count" />
          </Switch>
        </div>
      </div>
    </Router>
  );
};

但它总是重定向到主要组件。我怎么能做到像 /randomroute 这样的未定义路由会重定向到 "/" ,以及如何使替代路由 /count 工作?

编辑:我进步了一点

import React from "react";
import { BrowserRouter as Router, Route, Switch, RouteComponentProps, RouteProps } from "react-router-dom";
import Main from "./components/Main";
import Count from "./components/Count"
import "./App.css";

interface ChildComponentProps extends RouteProps {
  /* other props for ChildComponent */
}

const App: React.FunctionComponent<ChildComponentProps> = (props) => {
  return (
    <Router>
      <div className="main-content">
        <div>
          <Switch>
            <Route exactly component={Main} exact path="/" />
            <Route exactly component={Count} exact path="/count" />
            <Route pattern ="/" render={() => props.history.push("/") } />
          </Switch>
        </div>
      </div>
    </Router>
  );
};

export default App;

现在的问题是,历史在 RouteComponentProps 接口内,而 RouteProps 接口包含渲染,我不能同时使用它们,所以我有点失落

EDIT2:试试这个

   interface RenderProps extends RouteProps {
  /* other props for ChildComponent */
}
interface HistoryProps extends RouteComponentProps {

}

const App: React.FunctionComponent<HistoryProps & RenderProps>

在渲染中接收

预期的类型来自属性 'render',它在类型 'IntrinsicAttributes & IntrinsicClassAttributes<Route> & Readonly & Readonly<...>' 上声明

据说该接口已导入

编辑4:

我做了这个

import React from "react";
import { BrowserRouter as Router, Route, Switch, RouteComponentProps, RouteProps, withRouter  } from "react-router-dom";
import Main from "./components/Main";
import Count from "./components/Count"
import "./App.css";

interface RenderProps extends RouteProps {
  /* other props for ChildComponent */
}
interface HistoryProps extends RouteComponentProps {
    
}

const App: React.FunctionComponent<RenderProps & HistoryProps> = (props) => {
  return (
      <div className="main-content">
        <div>
          <Switch>
            <Route exactly component={Main} exact path="/" />
            <Route exactly component={Count} exact path="/count" />
            <Route path ="/" {...props.history.push("/")} />
          </Switch>
        </div>
      </div>
  );
};


export default withRouter(App);

并将 index.tsx 文件中的 app 组件包装到 (browserouter)

现在我得到一个

错误:超过最大更新深度。当组件在 componentWillUpdate 或 componentDidUpdate 中重复调用 setState 时,可能会发生这种情况。React 限制嵌套更新的数量以防止无限循环

因为 props.history.push

标签: reactjstypescriptreact-router

解决方案


我最终这样做了,但我在等待更好的答案

import React from "react";
import { Route, Switch, RouteComponentProps, withRouter} from "react-router-dom";
import Main from "./components/Main";
import Count from "./components/Count";
import Redirector from "./components/Redirect"
import "./App.css";


interface HistoryProps extends RouteComponentProps {
    
}


const App: React.FunctionComponent<HistoryProps> = (props) => {
  return (
      <div className="main-content">
        <div>
          <Switch>
            <Route exactly component={Main} exact path="/" />
            <Route exactly component={Count} exact path="/count" />
            <Route path ="/" exactly component={Redirector}/>
          </Switch>
        </div>
      </div>
  );
};


export default withRouter(App);

重定向.tsx

import * as React from "react";
import { Redirect   } from "react-router-dom";

const Redirector: React.FunctionComponent = () => {
  
  return <Redirect to='/'/>;
};

export default Redirector

EDIT2:可能是更好的方法

import React from "react";
import { Route, Switch, withRouter, Redirect} from "react-router-dom";
import Main from "./components/Main";
import Count from "./components/Count";
import "./App.css";


const App: React.FunctionComponent = () => {
  const renderFor404Routes = () => (<Redirect to='/'/>);
  return (
      <div className="main-content">
        <div>
          <Switch>
            <Route exactly component={Main} exact path="/" />
            <Route exactly component={Count} exact path="/count" />
            <Route path ="/" exactly component={renderFor404Routes}/>
          </Switch>
        </div>
      </div>
  );
};

export default withRouter(App);

推荐阅读