重定向到App.js中commponentDidMount上的url

时间:2018-10-16 20:15:19

标签: javascript reactjs react-router-v4 react-router-dom

我正在尝试在用户登录该应用并且尚未完成其个人资料时实施功能,因此应将其重定向到某个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行代码检查。

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>
    );
  }
}

More on React Router's redirect component here

答案 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方法也可以使用