2

I'm using the ReactRouter and want to do something like set state when the RouteNotFound component is hit (last one means no others above matched).

my this.handler does a setState so that I can tell that it was called. That of course gives me an error saying "Cannot update during an existing state transition such as in a render".

Is there a way I can set my state to tell me which (I really want to know the last one) of the switch statements go executed?

render() {
    return (
        <div>
            <Switch>
                <Route exact path="/" component={Home}/>
                <Route exact path="/p1" component={p1}/>
                <Route exact path="/p2" component={p2}/>
                <RouteNotFound action={this.handler} ></RouteNotFound>
            </Switch>
        </div>
    );
}
Pete
  • 3,111
  • 6
  • 20
  • 43
  • What you are looking for is the onEnter functionality of react-router which in react-router-v4 can be acieved through lifecycle methods. Check the duplicate question for implementation – Shubham Khatri Jan 03 '18 at 06:41

2 Answers2

5

Here we go:

not-found.js:

import React from 'react';
import { Route } from 'react-router-dom';

const RouteNoteFound = ({ action }) => (
  <Route
    render={props => (
      <NotFoundPageComponent action={action} />
    )}
  />
);


export default RouteNoteFound;

class NotFoundPageComponent extends React.Component {
  constructor(props) {
    super(props);
  }

  componentWillMount() {
    this.props.action()
  }

  render() {
    return (
      <div>404 not found</div>
    )
  }
}

and in index.js:

handler = () => {
    alert("alert from app.js but run in not found page")
}

render() {
    return (
      <BrowserRouter>
        <Switch>
          <Route exact path="/" component={Page} />
          <Route path="/page" component={Page} />
          <RouteNoteFound action={this.handler} />
        </Switch>
      </BrowserRouter>
    );
}

here is DEMO in stackblitz.

Emad Emami
  • 6,089
  • 3
  • 28
  • 38
  • in index.js, I want to push that "state" up to its parent and then again up to its parent. I think I want to set state in the action handler and then in ComponentDidUpdate, send the state up to parent. When I do that I get into recursion problem. – Pete Jan 03 '18 at 18:10
1

Try this.

Define the not found route like this:

<Route render={props => <RouteNotFound action={this.handler} />}></Route>

Because, as per the Doc:

A <Route> with no path prop or a <Redirect> with no from prop will always match the current location.

Check the Doc example for "No Path Match".

Now use componentDidMount lifecycle method in RouteNotFound component, whenever RouteNotFound will get rendered, componentDidMount will be called. Call the parent function from componentDidMount, like this:

componentDidMount(){
   this.props.action();
}

Now do setState inside action in parent component.

Mayank Shukla
  • 100,735
  • 18
  • 158
  • 142
  • The problem still exists in {this.handler}. I gather I can not do a state update inside the render function. Warning: Cannot update during an existing state transition (such as within `render` or another component's constructor). Render methods should be a pure function of props and state; constructor side-effects are an anti-pattern, but can be moved to `componentWillMount`. – Pete Jan 03 '18 at 05:11
  • what are you expection is in the {this.handler}. I've got the setState(...) in that which is causing the error I listed in the previous comment – Pete Jan 03 '18 at 05:16
  • not sure, why it is throwing error, are you using `()` with `this.handler` ? because it should work. It is working when doing setState inside `componentWillMount`? – Mayank Shukla Jan 03 '18 at 05:20