我正在尝试在用户登录该应用并且尚未完成其个人资料时实施功能,因此应将其重定向到某个URL,因此在他们尝试进行的所有操作(注销除外)中,都应将其重定向到complete-profile
网址。
我正在使用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
的错误,因为我猜想此方法被调用时它不需要任何道具,并且显示的错误是这样的:
未处理的拒绝(TypeError):无法读取未定义的属性“替换”
哪种是实施此方法的正确方法?
因为我不认为我应该对每个组件中的完整配置文件执行这4行代码检查。
答案 0 :(得分:2)
在App组件中,历史记录道具不可用(未定义),因为以下道具:
从Route组件传递到它的子组件(CompleteProfile,Home等)。因此,您不能在App组件中使用它们。
相反,您可以创建自己的Route组件:
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' />
)} />
)
}
}
并使用它而不是像这样的Route:
<CompleteProfile path='/' exact component={Home} />
这是您可以根据需要重构代码的一般想法。
答案 1 :(得分:1)
看一下Route组件的描述。例如,您将看到为使用<Route />
渲染的每个组件注入了三个prop。 <Route path="/login" component={Login} />
这些道具是match
location
history
在您的代码中,应用程序未使用Route呈现。因此,您无权使用这三个注入的道具。这就是为什么您会得到错误的历史记录未定义的原因。
要重定向用户,请改用如下所示的内容,您可以在其中有条件地呈现重定向或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>
);
}
}
答案 2 :(得分:0)
使用React时,这种TypeError变得非常熟悉。当您尝试使用“未定义”对象中的方法时,就会发生这种情况。
您可以确保this.props.history不会像这样未定义:
if (this.props.history && !completed)
this.props.history.replace("/complete-profile"); //error showing here
npm软件包“ Lodash”也可用于避免此类复杂情况。
答案 3 :(得分:0)
这只是个便宜的把戏。如果您想转到任何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方法也可以使用