异步请求后如何在路由中重定向?
How to redirect in routes after async request?
我有这段代码,其中我使用 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
在加载 App 组件之前在异步请求后被填充,结果是我第一次呈现时,我得到至 <NotFoundPage/>
。这是合乎逻辑的,但我如何才能先获取异步数据,然后才重定向?
临时解决了
<Route index element={<Navigate to={'/account/1'} />}/>`
但这并不能保证ID为1的元素永远存在于数组中
P.S. 数组 this.state.accounts
包含具有数字 属性 accountId
的对象。在 <TimelinePage/>
组件中,我使用 useParams()
获取帐户 ID,在 <AppLayout/>
组件中,我呈现数组的每个元素
使用 useNavigate
挂钩访问 navigate
函数并在获取帐户后发出命令式重定向。这里的问题是 App
是一个 class 组件,不能直接使用 React hooks。
选项是:
- 将
App
转换为函数组件。
- 创建自定义
withRouter
HOC 以访问挂钩并将 navigate
作为道具注入。
App
非常简单,转换为函数组件是微不足道的。
import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
const App = () => {
const navigate = useNavigate();
const [accounts, setAccounts] = useState([]);
useEffect(() => {
getAccounts()
.then(accounts => {
setAccounts(accounts);
navigate("/account/1", { replace: true });
});
}, []);
return (
<Routes>
<Route path="/" element={<AppLayout accounts={accounts} />}>
<Route path="/account/:accountId" element={<TimelinePage />} />
<Route path="*" element={<NotFoundPage />} />
</Route>
</Routes>
);
}
如果 class 组件更复杂,创建自定义 withRouter
HOC 并传入 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 App 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={<AppLayout accounts={accounts} />}>
<Route path="/account/:accountId" element={<TimelinePage />} />
<Route path="*" element={<NotFoundPage />} />
</Route>
</Routes>
);
}
}
export default withRouter(App);
我有这段代码,其中我使用 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
在加载 App 组件之前在异步请求后被填充,结果是我第一次呈现时,我得到至 <NotFoundPage/>
。这是合乎逻辑的,但我如何才能先获取异步数据,然后才重定向?
临时解决了
<Route index element={<Navigate to={'/account/1'} />}/>`
但这并不能保证ID为1的元素永远存在于数组中
P.S. 数组 this.state.accounts
包含具有数字 属性 accountId
的对象。在 <TimelinePage/>
组件中,我使用 useParams()
获取帐户 ID,在 <AppLayout/>
组件中,我呈现数组的每个元素
使用 useNavigate
挂钩访问 navigate
函数并在获取帐户后发出命令式重定向。这里的问题是 App
是一个 class 组件,不能直接使用 React hooks。
选项是:
- 将
App
转换为函数组件。 - 创建自定义
withRouter
HOC 以访问挂钩并将navigate
作为道具注入。
App
非常简单,转换为函数组件是微不足道的。
import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
const App = () => {
const navigate = useNavigate();
const [accounts, setAccounts] = useState([]);
useEffect(() => {
getAccounts()
.then(accounts => {
setAccounts(accounts);
navigate("/account/1", { replace: true });
});
}, []);
return (
<Routes>
<Route path="/" element={<AppLayout accounts={accounts} />}>
<Route path="/account/:accountId" element={<TimelinePage />} />
<Route path="*" element={<NotFoundPage />} />
</Route>
</Routes>
);
}
如果 class 组件更复杂,创建自定义 withRouter
HOC 并传入 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 App 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={<AppLayout accounts={accounts} />}>
<Route path="/account/:accountId" element={<TimelinePage />} />
<Route path="*" element={<NotFoundPage />} />
</Route>
</Routes>
);
}
}
export default withRouter(App);