我有一个代码,其中我使用react-router-dom v6进行路由

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      accounts: [],
    };
  }

  componentDidMount() {
    getAccounts().then(r => this.setState({ // async req
      accounts: r
    }));
  };

  render() {
    return (
      <Routes>
        <Route path="/" element={<AppLayout accounts={this.state.accounts} />}>
          <Route index element={<Navigate to={`/account/1`} />}/>
          <Route path="/account/:accountId" element={<TimelinePage/>}/>
          <Route path="*" element={<NotFoundPage/>}/>
        </Route>
      </Routes>
    );
  }
}

我想从主页重定向到/accounts/${this.state.accounts[0]},但在装载应用程序组件之前,在异步请求之后,数组this.state.accounts被填充,结果是,第一次渲染时,我得到了<NotFoundPage/>.这是合乎逻辑的,但如何才能先获取异步数据,然后再重定向?

我提出了一个临时解决方案

<Route index element={<Navigate to={'/account/1'} />}/>`

但这并不能保证ID为1的元素始终存在于数组中


P.S.数组this.state.accounts包含具有数字属性accountId的对象.在<TimelinePage/>组件中,我使用useParams()获取帐户id,在<AppLayout/>组件中,我渲染数组的每个元素

推荐答案

使用useNavigate钩子访问navigate函数,并在获取帐户后发出命令重定向.但这里的问题是应用程序是一个类组件,不能直接使用React钩子.

选项包括:

  1. Convert 应用程序 to a function component.
  2. 创建一个自定义的withRouter HOC来访问钩子,并将navigate作为props 注入.

应用程序非常简单,转换成函数组件非常简单.

import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';

const 应用程序 = () => {
  const navigate = useNavigate();
  const [accounts, setAccounts] = useState([]);

  useEffect(() => {
    getAccounts()
      .then(accounts => {
        setAccounts(accounts);
        navigate("/account/1", { replace: true });
      });
  }, []);

  return (
    <Routes>
      <Route path="/" element={<应用程序Layout accounts={accounts} />}>
        <Route path="/account/:accountId" element={<TimelinePage />} />
        <Route path="*" element={<NotFoundPage />} />
      </Route>
    </Routes>
  );
}

如果类组件更复杂,那么创建自定义的withRouter HOC并作为props 传入navigate可能会更容易.

import { useNavigate, ...other hooks... } from 'react-router-dom';

const withRouter = Component => props => {
  const navigate = useNavigate();
  ...other hooks...

  return (
    <Component
      {...props}
      navigate={navigate}
      ...other hooks...
    />
  );
};

应用程序

class 应用程序 extends Component {
  state = {
    accounts: [],
  }

  componentDidMount() {
    const { navigate } = this.props;
    getAccounts()
      .then(accounts => {
        this.setState({ accounts });
        navigate("/account/1", { replace: true });
      });
  }

  render() {
    const { accounts } = this.state;
    return (
      <Routes>
        <Route path="/" element={<应用程序Layout accounts={accounts} />}>
          <Route path="/account/:accountId" element={<TimelinePage />} />
          <Route path="*" element={<NotFoundPage />} />
        </Route>
      </Routes>
    );
  }
}

export default withRouter(应用程序);

Javascript相关问答推荐

为什么从liveWire info js代码传递数组我出现错误?

通过使用100%间隔时间来代表我们还剩多少时间来倒计时

当在select中 Select 选项时,我必须禁用不匹配的 Select

如何从JSON数组添加Google Maps标记—或者如何为数组添加参数到标记构造器

通过嵌套模型对象进行Mongoose搜索

使用复选框在d3.js多折线图中添加或删除线条

使搜索栏更改语言

Spring boot JSON解析错误:意外字符错误

在Vite React库中添加子模块路径

为什么!逗号和空格不会作为输出返回,如果它在参数上?

在执行异步导入之前判断模块是否已导入()

您能在卸载程序(QtInsteller框架)上添加WizardPage吗?

更新动态数据中对象或数组中的所有值字符串

为什么这个.add.group({})在教程中运行得很好,但在我的游戏中就不行了?

同一类的所有div';S的模式窗口

使用自动识别发出信号(&Q)

如何修复使用axios运行TSC index.ts时出现的错误?

有角粘桌盒阴影

如何调整下拉内容,使其不与其他元素重叠?

检测带有委托的元素内部的点击,以及元素何时按其类名被选中