私はこのPrivateRoute
コンポーネントを持っています(ドキュメントから):
_const PrivateRoute = ({ component: Component, ...rest }) => (
<Route {...rest} render={props => (
isAuthenticated ? (
<Component {...props}/>
) : (
<Redirect to={{
pathname: '/login',
state: { from: props.location }
}}/>
)
)}/>
)
_
isAuthenticated
をaysncリクエストisAuthenticated()
に変更したいと思います。ただし、応答が返される前に、ページがリダイレクトされます。
明確にするために、isAuthenticated
関数はすでに設定されています。
何を表示するかを決定する前に、非同期呼び出しが完了するのをどのように待つことができますか?
Reduxまたはその他の種類の状態管理パターンを使用していない場合は、Redirect
コンポーネントとコンポーネントの状態を使用して、ページをレンダリングするかどうかを決定できます。これには、状態を読み込み状態に設定する、非同期呼び出しを行う、リクエストが完了した後にユーザーを保存する、または基準が満たされない場合にRedirect
コンポーネントを状態にしてレンダリングするユーザーが不足していることが含まれます。 。
class PrivateRoute extends React.Component {
state = {
loading: true,
isAuthenticated: false,
}
componentDidMount() {
asyncCall().then((isAuthenticated) => {
this.setState({
loading: false,
isAuthenticated,
});
});
}
render() {
const { component: Component, ...rest } = this.props;
if (this.state.loading) {
return <div>LOADING</div>;
} else {
return (
<Route {...rest} render={props => (
<div>
{!this.state.isAuthenticated && <Redirect to={{ pathname: '/login', state: { from: this.props.location } }} />}
<Component {...this.props} />
</div>
)}
/>
)
}
}
}
@ pizza-r0bのソリューションは私にとって完璧に機能しました。ただし、ロードdivをルートの外側ではなく内側にレンダリングすることで、ロードdivが複数回(アプリ内で定義されたPrivateRouteごとに1回)表示されないように、ソリューションを少し修正する必要がありました( Reactと同様)ルーターの認証例 ):
class PrivateRoute extends React.Component {
constructor(props) {
super(props)
this.state = {
loading: true,
isAuthenticated: false
}
}
componentDidMount() {
asyncCall().then((isAuthenticated) => {
this.setState({
loading: false,
isAuthenticated
})
})
}
render() {
const { component: Component, ...rest } = this.props
return (
<Route
{...rest}
render={props =>
this.state.isAuthenticated ? (
<Component {...props} />
) : (
this.state.loading ? (
<div>LOADING</div>
) : (
<Redirect to={{ pathname: '/login', state: { from: this.props.location } }} />
)
)
}
/>
)
}
}
完全を期すためのApp.jsからの抜粋:
<DashboardLayout>
<PrivateRoute exact path="/status" component={Status} />
<PrivateRoute exact path="/account" component={Account} />
</DashboardLayout>
クラスコンポーネントの代わりにフックを使用した@CraigMylesの実装に興味がある人の場合:
export const PrivateRoute = (props) => {
const [loading, setLoading] = useState(true);
const [isAuthenticated, setIsAuthenticated] = useState(false);
const { component: Component, ...rest } = props;
useEffect(() => {
const fetchData = async () => {
const result = await asynCall();
setIsAuthenticated(result);
setLoading(false);
};
fetchData();
});
return (
<Route
{...rest}
render={() =>
isAuthenticated ? (
<Component {...props} />
) : loading ? (
<div>LOADING...</div>
) : (
<Redirect
to={{
pathname: "/login",
state: { from: props.location },
}}
/>
)
}
/>
);
};
これは、次のコマンドで呼び出すとうまく機能します。
<PrivateRoute path="/routeA" component={ComponentA} />
<PrivateRoute path="/routeB" component={ComponentB} />