Search code examples
reactjsreact-routerreact-router-domreact-contextreact-component

How to pass props from one page using a Link(react-router) to a class component


I have a Link in a page and I want it to pass the props to a route component which is a class component, how can I do that?? here is the code I have done so far:

the file where the Link is :

<List
    itemLayout="horizontal"
    dataSource={classes}
    renderItem={item => (
        <List.Item>
            <List.Item.Meta
                title = {
                    <Link 
                        to={{
                           pathname : "/Class",
                           state: {Name: item.Name}
                        }}
                        className="ListItem"
                    >
                        {item.Name}
                    </Link>
                 }
             />
         </List.Item>
       )}
/>

this is the index.js where I stored all the routes and I also have a context. Provider:

ReactDOM.render(
    <Provider store= {store}>
      <Router>
        <Layout>
          <Switch>
              <Route component={LandingPage} exact path="/" />
              <Route path="/dashboard" >
                <UserProvider>
                  <Dashboard/>
                </UserProvider>
              </Route>
              <Route path="/Class" >
                <UserProvider>
                  <Class/>
                </UserProvider>
              </Route>
              <Route component={NewMessage} path="/New-Message" />
              <Route path="/Inbox" >
                <UserProvider>
                  <Inbox/>
                </UserProvider>
              </Route>
              <Route path="/Outbox" >
                <UserProvider>
                  <Outbox/>
                </UserProvider>
              </Route>
              <Route component={ResetPassword} path="/reset-password" />
              <Route component={ResetPasswordConfirmed} path="/reset/password/confirm/:uid/:token" />
              <Route component={Signup} path="/signup" />
              <Route component={Activate} path="/activate/:uid/:token" />
            
          </Switch>
        </Layout>
      </Router>
    </Provider>,
  document.getElementById('root')
);

and this is the file that the link is pointing at (Class.js) :

class Class extends React.Component {
    
    static contextType = userContext
    
    state = {
        Curriculum: [],
        Classworks: [], 
        Homeworks: [],
        activeClass: ""
    }

    componentDidMount() {
        
        const { state } = props.location.state

        this.setState({
            activeClass: state
        });
        console.log(this.state.activeClass);        
      }

    render()
        {
            const { user_data, classes } = this.context
            return(
            <div className="back">
            <Navbar/>
            {this.state.activeClass}
            <main className= "MainContent">
                <div className="Class">
                    <h2 className="class">
                    </h2>
                </div>
            </main>
            <br/>
            <footer className="Footer">Designed by Eng. Omar Redwan</footer>
        </div>
        )}
}

export default Class;

Solution

  • Issue

    The Class component isn't directly rendered by a Route component so it doesn't receive the route props.

    <Route path="/Class" >
      <UserProvider>
        <Class/>
      </UserProvider>
    </Route>
    

    Solution

    Wrap the export of the Class component with the withRouter Higher Order Component so it has the route props injected to it.

    export default withRouter(Class);
    

    Now the Class component should be able to access route state via the location prop.

    const { location: { state } } = this.props;
    

    Side Note

    You can't log react state right after an enqueued update as react state updates are asynchronously processed between render cycles, so you'll only ever see the current state from the current render cycle.

    this.setState({
      activeClass: state
    });
    console.log(this.state.activeClass); // <-- current state!
    

    Use the componentDidUpdate lifecycle method to log state/prop updates.