在react router項目中,有這樣的一個需求髓梅,首先展示用戶名列表辜御,點擊某個用戶名后阁谆,根據(jù)用戶名在后臺取得用戶具體信息在詳情頁進行展示。
此時可以將詳情頁封裝成一個組件璧尸,利用react router將userId傳遞給詳情頁組件澎粟,詳情頁組件向后臺請求數(shù)據(jù),然后進行展示重贺。
component
使用component時,詳情頁組件代碼如下
import {PureComponent, Component} from "react";
import React from "react";
class ComponentUser extends PureComponent {
constructor(props) {
super(props);
this.state = {}
}
getUserId = () => {
const {
match: {
params: {id},
},
} = this.props;
return id;
};
fetchContent = (userId) => {
console.log("fetch");
this.setState({content: "loading"});
new Promise(resolve => {
setTimeout(() => {
resolve("content of " + userId)
}, 2000)
}).then(content => {
this.setState({content})
})
};
componentDidMount() {
const userId = this.getUserId();
this.fetchContent(userId);
}
render() {
const userId = this.getUserId();
const {content} = this.state;
return (
<div>
<div>{userId}</div>
<div>{content}</div>
</div>
)
}
}
export default ComponentUser
列表頁代碼如下
import React from "react";
import {BrowserRouter as Router, Route, Link} from "react-router-dom";
import RenderUser from './RenderUser'
import ComponentUser from './ComponentUser'
const App = () => (
<Router>
<div>
<nav>
<ul>
<li>
<Link to="/componentUser/user1">userA</Link>
</li>
<li>
<Link to="/componentUser/user2">userB</Link>
</li>
</ul>
</nav>
<Route path="/componentUser/:id" component={ComponentUser}/>
</div>
</Router>
);
export default App;
不過此時會有個問題崇堵,切換點擊切換userA和userB的時候,發(fā)現(xiàn)頁面并沒有更新涵紊,這是由component屬性的性質(zhì)決定的驱负,react會進行組件復用。
所以需要在組件中添加componentDidUpdate函數(shù),期望在userId發(fā)生變化后重新獲取數(shù)據(jù)拼缝。
import {PureComponent, Component} from "react";
import React from "react";
class ComponentUser extends PureComponent {
constructor(props) {
super(props);
this.state = {}
}
getUserId = () => {
const {
match: {
params: {id},
},
} = this.props;
return id;
};
fetchContent = (userId) => {
console.log("fetch");
this.setState({content: "loading"});
new Promise(resolve => {
setTimeout(() => {
resolve("content of " + userId)
}, 2000)
}).then(content => {
this.setState({content})
})
};
componentDidMount() {
const userId = this.getUserId();
this.fetchContent(userId);
}
componentDidUpdate(prevProps) {
const userId = this.getUserId();
const {
match: {
params: {id: previousUserId},
},
} = prevProps;
if (userId !== previousUserId) {
this.fetchContent(userId);
}
}
render() {
const userId = this.getUserId();
const {content} = this.state;
return (
<div>
<div>{userId}</div>
<div>{content}</div>
</div>
)
}
}
export default ComponentUser
這里要注意的是瘟檩,componentDidUpdate中需要判斷當前的userId是否和原來的userId一致,只有不一致的時候才需要重新獲取數(shù)據(jù)奏赘。不這樣做的話梁只,會導致無限循環(huán)的setState和componentDidUpdate。
render
使用render則可以減少三分之一的代碼行數(shù)翰绊,此時詳情頁組件代碼如下
import {PureComponent} from "react";
import React from "react";
class RenderUser extends PureComponent {
constructor() {
super();
this.state = {}
}
componentDidMount() {
console.log("fetch");
this.setState({content: "loading"});
const {userId} = this.props;
new Promise(resolve => {
setTimeout(() => {
resolve("content of " + userId)
}, 1000)
}).then(content => {
this.setState({content})
})
}
render() {
const {userId} = this.props;
const {content} = this.state;
return (
<div>
<div>{userId}</div>
<div>{content}</div>
</div>
)
}
}
export default RenderUser
列表頁代碼如下
import React from "react";
import {BrowserRouter as Router, Route, Link} from "react-router-dom";
import RenderUser from './RenderUser'
import ComponentUser from './ComponentUser'
const App = () => (
<Router>
<div>
<nav>
<ul>
<li>
<Link to="/renderUser/user1">user1</Link>
</li>
<li>
<Link to="/renderUser/user2">user2</Link>
</li>
</ul>
</nav>
<Route path="/renderUser/:id" render={
({match}) => (<RenderUser key={match.params.id} userId={match.params.id}/>)
}/>
</div>
</Router>
);
export default App;
可以看到由于將userId作為組件的key溃肪,可以避免組件復用,從而降低代碼的復雜程度。