在 App.js 中的 componentDidMount 上重定向到 url
Redirect to url on commponentDidMount in App.js
我正在尝试实现一个功能,当用户登录到应用程序并且他们还没有完成他们的个人资料时,他们应该被重定向到某个 URL,所以他们试图去的任何地方(注销除外)他们应该被重定向到 complete-profile
URL.
我正在使用 react-router-dom
包处理路由。
App.js
class App extends Component {
async componentDidMount() {
const logged = isLoggedIn();
if (logged) {
const completed = await hasCompleted();
if (!completed) this.props.history.replace("/complete-profile"); //error showing here
}
}
render() {
return (
<React.Fragment>
<NavBar />
<main className="container">
<Switch>
<Route path="/complete-profile" component={CompleteProfile} />
<Route path="/login" component={Login} />
<Route path="/register" component={Register} />
<Route path="/logout" component={Logout} />
<Route path="/" exact component={Home} />
</Switch>
</main>
</React.Fragment>
);
}
}
所以基本上我在 componentDidMount
方法中尝试做的是:我首先检查用户是否登录。然后检查用户是否已完成他们的个人资料,如果没有完成则它应该重定向到 /complete-profile
URL.
但是使用此方法时我遇到了 this.props.history.replace
的错误,因为我猜调用此方法时它没有使用任何道具,显示的错误是:
Unhandled Rejection (TypeError): Cannot read property 'replace' of undefined
实施此方法的正确方法是什么?
因为我认为我不应该在每个组件中实施这 4 行代码来检查完整的配置文件。
这种 TypeError 在使用 React 时变得非常熟悉。当您尝试使用来自 "undefined".
对象的方法时,会发生这种情况
你可以确保 this.props.history 不是像这样未定义的:
if (this.props.history && !completed)
this.props.history.replace("/complete-profile"); //error showing here
npm 包 'Lodash' 也可用于避免这些并发症。
这只是一个卑鄙的把戏。如果您想转到任何 url(包括 React 或任何其他前端框架),只需执行:
window.location.replace(str)
str 可以是绝对路径,如“https://abcd.com”,也可以是相对路径,如(“/complete-profile”,它将成为 baseurl + “/complete-profile”)
if (logged) {
const completed = await hasCompleted();
if (!completed) window.location.replace("/complete-profile"); //error showing here
}
@zacks 方法也有效
在 App 组件中,history 属性不可用(未定义),因为以下属性:
- 历史
- 位置
- 匹配
从 Route 组件传递给它的子组件(CompleteProfile、Home、....)。所以你不能在App组件中使用它们。
相反,您可以创建自己的路由组件:
class CompleteProfile extends Component {
state = {
completed: false
};
async componentDidMount() {
const logged = isLoggedIn();
if (logged) {
const completed = await hasCompleted();
this.setState({completed});
//error showing here
}
}
render() {
const { component: Component, ...rest } = this.props;
const { completed } = this.state;
return (
<Route {...rest} render={(props) => (
completed
? <Component {...props} />
: <Redirect to='/complete-profile' />
)} />
)
}
}
并使用它代替这样的路线:
<CompleteProfile path='/' exact component={Home} />
这是您可以根据需要重构代码的总体思路。
查看 Route 组件的说明。例如,您会看到为代码中使用 <Route />
呈现的每个组件注入了三个道具。 <Route path="/login" component={Login} />
这些道具是match
location
history
在您的代码中,应用程序未使用路由呈现。因此,您无权访问这三个注入的道具。这就是为什么你得到历史未定义的错误的原因。
要重定向用户,请改用类似下面的内容,您可以在其中有条件地呈现重定向或 UI,具体取决于数据是否存在。
class App extends Component {
constructor(props){
super(props);
this.state = {
fetchingStatus: true,
completed: false
};
}
async componentDidMount() {
const logged = isLoggedIn();
if (logged) {
const completed = await hasCompleted();
if (!completed) this.setState({ fetchingStatus: false, completed: true })
}
}
render() {
const { fetchingStatus, completed } = this.state;
// Render nothing, or a spinner as loading indicator
if (fetchingStatus) return null; // waiting for details...
// if data was fetched and registeration not completed, render redirect.
if (!fetchingStatus && !completed) return <Redirect to="/complete-profile" />
// Render switch and nav.
return (
<React.Fragment>
<NavBar />
<main className="container">
<Switch>
<Route path="/complete-profile" component={CompleteProfile} />
<Route path="/login" component={Login} />
<Route path="/register" component={Register} />
<Route path="/logout" component={Logout} />
<Route path="/" exact component={Home} />
</Switch>
</main>
</React.Fragment>
);
}
}
我正在尝试实现一个功能,当用户登录到应用程序并且他们还没有完成他们的个人资料时,他们应该被重定向到某个 URL,所以他们试图去的任何地方(注销除外)他们应该被重定向到 complete-profile
URL.
我正在使用 react-router-dom
包处理路由。
App.js
class App extends Component {
async componentDidMount() {
const logged = isLoggedIn();
if (logged) {
const completed = await hasCompleted();
if (!completed) this.props.history.replace("/complete-profile"); //error showing here
}
}
render() {
return (
<React.Fragment>
<NavBar />
<main className="container">
<Switch>
<Route path="/complete-profile" component={CompleteProfile} />
<Route path="/login" component={Login} />
<Route path="/register" component={Register} />
<Route path="/logout" component={Logout} />
<Route path="/" exact component={Home} />
</Switch>
</main>
</React.Fragment>
);
}
}
所以基本上我在 componentDidMount
方法中尝试做的是:我首先检查用户是否登录。然后检查用户是否已完成他们的个人资料,如果没有完成则它应该重定向到 /complete-profile
URL.
但是使用此方法时我遇到了 this.props.history.replace
的错误,因为我猜调用此方法时它没有使用任何道具,显示的错误是:
Unhandled Rejection (TypeError): Cannot read property 'replace' of undefined
实施此方法的正确方法是什么?
因为我认为我不应该在每个组件中实施这 4 行代码来检查完整的配置文件。
这种 TypeError 在使用 React 时变得非常熟悉。当您尝试使用来自 "undefined".
对象的方法时,会发生这种情况你可以确保 this.props.history 不是像这样未定义的:
if (this.props.history && !completed)
this.props.history.replace("/complete-profile"); //error showing here
npm 包 'Lodash' 也可用于避免这些并发症。
这只是一个卑鄙的把戏。如果您想转到任何 url(包括 React 或任何其他前端框架),只需执行:
window.location.replace(str)
str 可以是绝对路径,如“https://abcd.com”,也可以是相对路径,如(“/complete-profile”,它将成为 baseurl + “/complete-profile”)
if (logged) {
const completed = await hasCompleted();
if (!completed) window.location.replace("/complete-profile"); //error showing here
}
@zacks 方法也有效
在 App 组件中,history 属性不可用(未定义),因为以下属性:
- 历史
- 位置
- 匹配
从 Route 组件传递给它的子组件(CompleteProfile、Home、....)。所以你不能在App组件中使用它们。
相反,您可以创建自己的路由组件:
class CompleteProfile extends Component {
state = {
completed: false
};
async componentDidMount() {
const logged = isLoggedIn();
if (logged) {
const completed = await hasCompleted();
this.setState({completed});
//error showing here
}
}
render() {
const { component: Component, ...rest } = this.props;
const { completed } = this.state;
return (
<Route {...rest} render={(props) => (
completed
? <Component {...props} />
: <Redirect to='/complete-profile' />
)} />
)
}
}
并使用它代替这样的路线:
<CompleteProfile path='/' exact component={Home} />
这是您可以根据需要重构代码的总体思路。
查看 Route 组件的说明。例如,您会看到为代码中使用 <Route />
呈现的每个组件注入了三个道具。 <Route path="/login" component={Login} />
这些道具是match
location
history
在您的代码中,应用程序未使用路由呈现。因此,您无权访问这三个注入的道具。这就是为什么你得到历史未定义的错误的原因。
要重定向用户,请改用类似下面的内容,您可以在其中有条件地呈现重定向或 UI,具体取决于数据是否存在。
class App extends Component {
constructor(props){
super(props);
this.state = {
fetchingStatus: true,
completed: false
};
}
async componentDidMount() {
const logged = isLoggedIn();
if (logged) {
const completed = await hasCompleted();
if (!completed) this.setState({ fetchingStatus: false, completed: true })
}
}
render() {
const { fetchingStatus, completed } = this.state;
// Render nothing, or a spinner as loading indicator
if (fetchingStatus) return null; // waiting for details...
// if data was fetched and registeration not completed, render redirect.
if (!fetchingStatus && !completed) return <Redirect to="/complete-profile" />
// Render switch and nav.
return (
<React.Fragment>
<NavBar />
<main className="container">
<Switch>
<Route path="/complete-profile" component={CompleteProfile} />
<Route path="/login" component={Login} />
<Route path="/register" component={Register} />
<Route path="/logout" component={Logout} />
<Route path="/" exact component={Home} />
</Switch>
</main>
</React.Fragment>
);
}
}