15

I've seen similar posts but couldn't find an answer and in my case, I'm trying to pass an action from <App />:

  addExpense = (expense) => {
    console.log('Hello From AddExpenseForm');
  }

to /create route where I'm rendering <AddExpenseForm /> component

<Link to={{
  pathname: '/create',
  state: { addExpense: this.addExpense }
}}> Create Expense</Link>

The link is rendered but when I click on it I get an error in console:

Uncaught DOMException: Failed to execute 'pushState' on 'History': function (expense) {
      console.log('Hello From addExpense');
    } could not be cloned

Why is that and what's the workaround here?

My updated code:

Routes in Index.js:

const Routes = () => {
  return (
      <BrowserRouter>
        <Switch>
          <Route path="/" exact component={App} />
          <Route path="/create" exact component={AddExpenseForm}/>
          <Route path="/expense/:expenseId" name="routename" component={ExpenseDetails} />
          <Route component={NotFound} />
        </Switch>
      </BrowserRouter>
  )
}

App.js:

  addExpense = (expense = {}) => {
    console.log('Hello From AddExpenseForm');
  }

  goToNextPage = (addExpense) => {
    this.props.history.push({
      pathname: '/create',
      state: { addExpense: this.addExpense }
    });
  }

  render() {
    return (
      <div>
        <Header
        />
        <button onClick={this.goToNextPage}>Create</button>
        ...
BlackBeard
  • 10,246
  • 7
  • 52
  • 62
karolis2017
  • 2,195
  • 8
  • 24
  • 49
  • Try checking out [this similar question](https://stackoverflow.com/questions/24425885/failed-to-execute-pushstate-on-history-error-when-using-window-history-pushs). Maybe also try not pushing the `addExpense()` function to state. I suspect this problem is an offshoot of a previous problem you were trying to solve recently, regarding passing props between routes. Please see my answer to that for more info. – Arman Charan Oct 18 '17 at 00:25
  • Thanks for the link. I have seen this explanation but is there a solution for that? "use sessionStorage and/or localStorage". How do I implement that in this case? I'm quite a novice. – karolis2017 Oct 18 '17 at 01:25
  • Apologies for the lack of clarity. That solution was left pre ReactJS / React Router. Not an appropriate implementation for your use case, but still useful to understand the error. – Arman Charan Oct 18 '17 at 02:03

6 Answers6

7

Firstly, add some default value to your addExpense function:

  addExpense = (expense = DEFAULT) => {
    console.log('Hello From addExpense');
  }

Then Use Link:

<Link to={`/ideas/${this.addExpense}`}>Create Expense​</Link>         

OR Try this (Better Approach):

  goToNextPage = (addExpense) => {
    this.props.history.push({
      pathname: '/create',
      state: { addExpense: addExpense }
    });
  }

In next (create) component use the passed on values like this:

this.props.location.state.addExpense();
BlackBeard
  • 10,246
  • 7
  • 52
  • 62
  • 1
    Thanks, how do I implement that goToNextPage? I create a button with `onClick={this.goToNextPage}`but getting an error `Cannot read property 'props' of undefined` – karolis2017 Oct 18 '17 at 07:12
  • @karolis2017 use `fat arrow '=>'` or do `{this.goToNextPage.bind(this)}`. Also updated my answer. – BlackBeard Oct 18 '17 at 07:17
  • 4
    now getting this `DataCloneError: Failed to execute 'pushState' on 'History': [object Object] could not be cloned.` – karolis2017 Oct 18 '17 at 07:19
  • can you replicate your issue [here](https://codepen.io/bradleyboy/pen/OPBpGw?editors)? – BlackBeard Oct 18 '17 at 07:33
  • how do I do routes in codepen? how do I do `import from 'react-router-dom';`? – karolis2017 Oct 18 '17 at 07:38
  • @karolis2017 U'll have to create a id for that I guess. But, can you replicate your issue anywhere online? Github? Or help me re-create your issue on my side? – BlackBeard Oct 18 '17 at 07:45
  • this is the repo with current code: https://github.com/kstulgys/expenses-ci-app I hope this helps – karolis2017 Oct 18 '17 at 07:57
7

In my case, it was caused by trying to route to a path with two "/" characters. I wrote this:

history.push(`${location.pathname}/somePath`);

... but if location.pathname is "/" that will try to go to "//somePath", causing the error,

Nicholas Tower
  • 72,740
  • 7
  • 86
  • 98
3

You are using BrowserRouter which uses HTML5 history API(window.history), unlike Router and HashRouter.

Mapping of BrowserRouter's history.push method to HTML5 history is below:

this.props.history.push({
  pathname: '/create',
  state: { addExpense: this.addExpense }
});

pathname('/create') > window.history.push('create')

state({ addExpense: this.addExpense }) > window.history.pushState({ addExpense: this.addExpense })

The actual issue is with window.history.pushState as it stores the state as a string and has size limit of 640k characters.

Source: https://developer.mozilla.org/en-US/docs/Web/API/History/pushState

Jaspreet Singh
  • 1,672
  • 1
  • 14
  • 21
2

In my case, I was using BrowserRouter and found out that I either needed to run a local server or switch to HashRouter since BrowserRouter does not work with a file:// path due to security reasons.

https://github.com/ReactTraining/react-router/issues/6533#issuecomment-451969973

datchung
  • 3,778
  • 1
  • 28
  • 29
2

I was getting the same issue but when I changes all my backward slashes to forward slashes like below , error got resolved :-

 <li><NavLink to="/">Home</NavLink></li>
               <li><NavLink to="/About">About</NavLink></li>
               <li><NavLink to="/Contact">Contact</NavLink></li>
0

For anyone still struggling with this, this is what worked for me : Below is the page where you want to navigate:

export default function details(details): {....}

Below is the page from where you will navigate:

export default function starting() {
....
const history = useHistory()
history.push({
                pathname:"/details",
                details
            })
}

Notice how I didn't pass anything like {state:details}. I'm just directly passing the array.

KKM
  • 626
  • 5
  • 12