3

I'm having a problem with react-router when trying to pass setState from the useState hook using <Link>. What am I doing wrong?

I created simple project to show the problem: https://codesandbox.io/s/restless-surf-mj2vx?fontsize=14

Open console and click on the link to see the error.

  const [state, setState] = useState(0);

  return (
    <div className="App">
      <Link to={{ pathname: "/test", state: { state, setState } }}>test</Link>
      <Switch>
        <Route path="/test" component={Test} />
      </Switch>
    </div>
  );
}

I'm getting this error that does not help me resolve the issue:

"Uncaught DOMException: Failed to execute 'pushState' on 'History': function () { [native code] } could not be cloned."

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Jan Jaworski
  • 139
  • 3
  • 12
  • 1
    It's trying to clone what you're passing as `state` to the `Link`, but can't clone the `setState` function. Why *are* you passing that as state? – jonrsharpe Jun 05 '19 at 10:03
  • Possible duplicate of [Failed to execute 'pushState' on 'History' error when using window.history.pushState function](https://stackoverflow.com/questions/24425885/failed-to-execute-pushstate-on-history-error-when-using-window-history-pushs) – ponury-kostek Jun 05 '19 at 10:03
  • what's a point to pass `setState` updater callback when navigating away from current component? – skyboyer Jun 05 '19 at 10:05

1 Answers1

3

If you need the setState function in the <Test /> component, pass it with the route instead:

const [state, setState] = useState(0);

return (
    <div className="App">
        <Link to={{ pathname: '/test' }}>test</Link>
        <Switch>
            <Route
                path="/test"
                render={props => (
                    <Test {...props} state={state} setState={setState} />
                )}
            />
        </Switch>
    </div>
);
Oscar
  • 1,250
  • 13
  • 19
  • Thanks for the answer. This makes sense. Would you consider using context in this case? My main motivation to pass it in was to update array kept in state of the parent component. As the link led to form that added a new element to the list. It seems that in this case context would allow managing it in a better way. – Jan Jaworski Jun 05 '19 at 11:35
  • 1
    Use context if it becomes unwieldy passing `state` and `setState` several levels deep, otherwise it's probably not the right solution. I would always start without using context, unless I know it's something that all components, everywhere, might need (logged in state and language settings for instance). – Oscar Jun 05 '19 at 11:42