Создали приложение react (с использованием npx create-react-app), которое вылетает при обновлении

#reactjs #react-router

#reactjs #react-router

Вопрос:

Я создал приложение react (с помощью npx create-react-app), и я извлекаю данные api (пользователя) с помощью axios, а затем отображаю данные в компоненте (UsersList.js ) затем по щелчку конкретного пользователя он переходит к UserHomePage.js (с данными пользователя). При обновлении страницы UserHome приложение выходит из строя с сообщением об ошибке (не удается прочитать свойство undefined). Main.js является корневым для всех компонентов.

Ссылка на GitHub: https://github.com/ajitkrsingh0786/users-profile-react-app Ссылка Netlify: https://ajit-users-profile-react-app.netlify.app/

Мои коды..

index.js

 import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

 
serviceWorker.unregister();
  

App.js

 import React from 'react';
import './App.css';
import Main from './components/Main';
import { HashRouter, useHistory } from 'react-router-dom';
 
 
function App() {
   
  return (
    <HashRouter>
      <div className="App">
        <Main />
      </div>
    </HashRouter>
  );
}

export default App;
  

Main.js

 import React ,{Component} from 'react';
import UsersList from './UsersList';
import UserHomePage from './UserHomePage';
import { Switch, Route, Redirect } from 'react-router-dom';
import Axios from 'axios';


class Main extends  Component{
    constructor(props){
           super(props);
           this.state = {
               users: [],
               
           }
    }


        componentDidMount(){
        Axios.get('https://panorbit.in/api/users.json')            
             .then( res => {
                 console.log(res)
                 this.setState(
                     {
                         
                         users: res.data.users,
                     }
                 )
             })
    }
      
    render(){

        const UserWithId = ({match}) => {
            return(
                <UserHomePage user={this.state.users.filter((user) => user.id === parseInt(match.params.userId,10))[0]} />
            );
          };
     
          
        return (
            <div>
             <Switch>
              <Route path='/userList' component={ () =><UsersList users={this.state.users}/>} />
              <Route exact path='/userHomePage' component={UserHomePage} />
              <Route path='/userHomePage/:userId'  component={UserWithId}/>
              <Redirect to="/userList"/>
          </Switch>
            </div>
        )
    }
}

export default Main;
  

UsersList.js

 import React from 'react';
import { Card, CardImg, CardImgOverlay, CardText, CardBody, CardHeader,
    CardTitle, Container} from 'reactstrap';
    import {Link} from 'react-router-dom';
 
  function UsersList(props){
         console.log("Ajit");
         console.log(props)
          

      return(
               <Container className="users-list-container">
                <div className="col-5">
                <Card className="users-list-card">
                    <CardHeader>
                        <h4>Users List</h4>
                    </CardHeader>
                <CardBody className="card-body" >
                <ul className="users-list">
                    {
                        props.users.map( user => {
                            return(
                            <Link to={`/userHomePage/${user.id}`} key={user.id}>
                            <li key={user.id}>
                               <div className="user-image user-row">
                                   <img src={user.profilepicture} alt="img" className="user- 
                                    image"/>
                                </div>

                                <div className="user-row">
                                     {user.name}
                                </div>
                                
                                </li>
                                </Link>
                            )
                        })
                    }
                </ul>
                </CardBody>
                </Card>
                </div>
                </Container>
      )
  }

  export default UsersList;
  

UserHomePage.js

 import React from 'react';
import { Container } from 'reactstrap';
import { useHistory } from 'react-router-dom';
 
  function UserHomePage( props ){

    const history = useHistory();
  console.log("history");
  console.log(history);
  console.log("history");
      return(
          <div  className="home-page">
              <div className="nav-bar">
                  <ul className="ul-nav-bar">
                    <li className="li-nav-bar"> <h4>Profile</h4> </li>
                    <li className="li-nav-bar"> <h4>Posts</h4>  </li>
                    <li className="li-nav-bar"> <h4>Gallery</h4></li>
                    <li className="li-nav-bar">  <h4>ToDo</h4>  </li>                  
                  </ul>                                      
              </div>
              <div  className="home-page-body">
                  <div className="row-1">
                       <h4 className="row-1">Users Home page</h4>
                         <div className="user-image user-row">
                                   <img src={props.user.profilepicture} alt="img" 
                                     className="user-image"/>
                                </div>

                                <div className="user-row">
                                     {props.user.name}
                        </div>
                  </div>
                  <div className="row-2">
               
               <img src={props.user.profilepicture} alt="user image" />
               </div>
             </div>
          </div>
      )
  }

  export default UserHomePage;

  

Ответ №1:

Когда вы переходите на первую страницу /userlist , вызов API для данных в componentdidmount выдает вам данные. А затем вы перенаправляете на /userHomePage/:userId страницу при нажатии на конкретную пользовательскую ссылку со страницы списка пользователей. Теперь, поскольку данные для этого компонента, которые вы создали при рендеринге, уже были там, компонент монтировался

 const UserWithId = ({
    match
}) => {
    return ( <
        UserHomePage user = {
            this.state.users.filter((user) => user.id === parseInt(match.params.userId, 10))[0]
        }
        />
    );
};
  

но когда вы обновляете страницу /userHomePage/:userId , тогда рендеринг для Main.js вызывается первым, когда состояние пустое, и, следовательно, фильтр, который вы использовали в приведенном выше определении в этом рендеринге, даст вам неопределенный объект. Таким образом, в компоненте UserHomePage undefined создает ошибку, и метод componentDidMount вызываться не будет.
Решение этого может быть связано с использованием нулевых проверок в UserHomePage
Таким образом, код для UserHomePage будет

 import React from 'react';
import { Container } from 'reactstrap';
 
  function UserHomePage( props ){
      return(
          <div  className="home-page">
              <div className="nav-bar">
                  <ul className="ul-nav-bar">
                    <li className="li-nav-bar"><h4>Profile</h4></li>
                    <li className="li-nav-bar"><h4>Posts</h4></li>
                    <li className="li-nav-bar"><h4>Gallery</h4></li>
                    <li className="li-nav-bar"><h4>ToDo</h4></li>                  
                  </ul>                                      
              </div>
              <div  className="home-page-body">
                  <div className="row-1">
                       <h4 className="row-1">Users Home page</h4>
                        <div className="user-image user-row">
                                   <img src={props.user amp;amp; props.user.profilepicture} alt="img" className="user-image"/>
                                </div>

                                <div className="user-row">
                                     {props.user amp;amp; props.user.name}
                        </div>
                  </div>
                  <div className="row-2">
               <img src={props.user amp;amp; props.user.profilepicture} alt="user image" />
               </div>
             </div>
          </div>
      )
  }

  export default UserHomePage;
  

Так что сначала он будет отображать пустые данные, а затем после componentDidMount он будет печатать фактические отфильтрованные пользовательские данные