【问题标题】:Uncaught DOMException: Failed to execute 'pushState' on 'History': function () { [native code] } could not be cloned未捕获的 DOMException:无法在“历史”上执行“pushState”:无法克隆函数(){[本机代码]}
【发布时间】:2018-05-31 06:44:47
【问题描述】:

我正在使用 Visual Studio 2017 提供的 reactjs 模板创建一个小型 Web 应用程序。我陷入了一种情况,我希望将一个函数作为状态传递给子组件,然后通过子组件调用该函数。我有一个标头组件,其中有一个名为 setLogInTrue() 的方法,我想将其传递给我的 SignIn 组件。以下是我的代码:-

Header.tsx

class HeaderState {
isLoggedIn: boolean;
}

export class Header extends React.Component<HeaderProps, HeaderState> {
constructor() {
    super()
    this.state = ({ isLoggedIn: false });
    this.setLogInTrue= this.setLogInTrue.bind(this);
}

setLogInTrue() {
    this.setState({ isLoggedIn: true });
}

public render(){
//Some elements
<NavLink className="link header_row_link" to={{ pathname: '/signIn', state: this.setLogInTrue }}> //<-- i thought this would work and give the function in the location of SignIn components state but it does not.
              Sign In
</NavLink>
  }
}

登录.tsx

export class SignIn extends React.Component<RouteComponentProps<{}>, {}>  {

constructor() {
    super();
}

public render() {
    return <div className="signin_wrapper">
        <SignInContent />
    </div>;
  }
}

我想在此处访问该函数并将其传递给 SignInContent 组件,然后从那里调用该函数。

这段代码没有给我任何编译时错误,但是每当我点击登录链接时,它都会给我以下错误

未捕获的 DOMException:无法在“历史”上执行“pushState”:无法克隆 function () { [native code] }。

我尝试了this 解决方案,但它对我不起作用。它仍然给我这个错误或给状态为未定义。我很新的反应,任何帮助将不胜感激

【问题讨论】:

  • 来自MDN: "pushState() 接受三个参数:state 对象、标题和 URL。" -> "状态对象可以是任何可以序列化" -> "从Gecko 6.0 (Firefox 6.0 ...)开始,对象使用结构化克隆算法。" -> "结构化克隆不起作用的东西:ErrorFunction 对象 不能被结构化克隆算法复制;尝试这样做将引发 DATA_CLONE_ERR 异常。"
  • 如果该功能不被允许,那么是否有替代方法?

标签: reactjs typescript visual-studio-2017


【解决方案1】:

正如@Andreas 在评论中提到的那样,当在通过history.replaceStatehistory.pushState 分配给window.history.state 的状态对象中使用DOM 元素或任何不可序列化的东西时,就会发生此错误。例如尝试:history.pushState({node: document.body}, 'title', '#/error') 或改用{node: History},它会产生类似的DOMException 错误。要修复它,只需删除有问题的对象,或者以某种方式更慎重地考虑将什么推入状态。

【讨论】:

    【解决方案2】:

    当 React 组件状态包含非序列化对象时,我遇到了同样的问题。

    我只需要将整个 React 状态对象字符串化,然后再将其推送到浏览器的历史状态,如下所示:

    window.history.pushState(JSON.stringify(state), "", getSecuredURL(url));
    

    【讨论】:

    • 小心! JSON.parse() 不能很好地处理日期和其他事情。
    【解决方案3】:

    在推送包含函数的 React 组件状态时,我也遇到了同样的问题。我不想打电话给JSON.strinfigy,因为它可以包含日期并且那些不能很好地字符串化/解析。相反,我选择这样做:

    window.history.pushState(cleanStateForHistory(state), "", someURL);
    
    /**
     * Remove the functions from the state. They can't been pushed into the history.
     */
    export function cleanStateForHistory(state) {
      const stateWithNoFunctions = {};
      for (const key of Object.keys(state)) {
        if (typeof key !== "function") {
          stateWithNoFunctions[key] = state[key];
        }
      }
      return stateWithNoFunctions;
    }
    
    

    【讨论】:

      猜你喜欢
      • 2018-03-06
      • 1970-01-01
      • 2019-09-16
      • 1970-01-01
      • 2018-05-06
      • 2021-03-28
      • 1970-01-01
      • 2021-10-25
      • 1970-01-01
      相关资源
      最近更新 更多