6

我们正在将Okta 登录小部件集成到我们基于 React 的 web 应用程序中。

示例片段

var oktaSignIn = new OktaSignIn({baseUrl: baseUrl});
oktaSignIn.renderEl(...)

第一次渲染小部件时对我们来说效果很好,但是在用户登录并再次注销后,webapp 会再次渲染登录组件并尝试renderEl再次执行以渲染小部件。这会导致引发以下异常:

Backbone.history has already been started

我创建了这个 jsfiddle来演示这个问题。它只是两次实例化一个登录小部件(等待后的第二次)。您可以看到第二次调用导致抛出异常。

https://jsfiddle.net/nudwcroo/6/

目前我的解决方法是在登录组件时重新加载整个 web 应用程序,但这对于单页应用程序来说是不可取的。

这是一个已知的问题?有没有办法在一个 javascript 会话中两次初始化登录小部件?

4

2 回答 2

0

由于小部件每页只能实例化一次,因此最好隐藏/显示所有单页应用程序的元素。

<div id="okta-login-container"></div>

<script type="text/javascript">
    var oktaSignIn = new OktaSignIn(/* config */);

    oktaSignIn.renderEl(
      { el: '#okta-login-container' },
      function (res) {
        if (res.status === 'SUCCESS') {
            // Hide element 
            $("#okta-login-container").hide();
        }
      }
    );
</script>

创建logout()函数时,请确保show()元素而不是再次渲染它。

function logout() {
    $('#okta-login-container').show();
    // Do more logic
}
于 2017-02-02T22:27:35.580 回答
0

对于那些在遵循此处提供的 Okta 示例后遇到类似问题的人:(https://github.com/okta/samples-js-react/blob/master/custom-login/src/Login.jsx

问题在于尝试在单个页面应用程序中多次初始化小部件。我通过仅在 App 级别初始化小部件一次,然后在子组件挂载/卸载时渲染它并从 DOM 中删除它来解决此问题。

例子:

//App.js
class App extends Component {
  constructor() {
    super()
    this.signIn = new OktaSignIn({...})
  }

  render() {
    return <SignInPage widget={this.signIn} />
  }
}

--

//SignInPage.js
...
  componentDidMount() {
    let { redirectUri } = this.state
    let { widget } = this.props
    widget.renderEl(
      { el: '#sign-in-widget' },
      (response) => {
        response.session.setCookieAndRedirect(redirectUri)
      },
      (error) => {
        throw error;
      },
    );

  }

  componentWillUnmount() {
      let { widget } = this.props
      widget.remove()
  }

  render() {
    return  <div id="sign-in-widget"/></div>
  }
于 2019-01-29T20:17:53.363 回答