#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 он будет печатать фактические отфильтрованные пользовательские данные