了解react router 4
的动态路由,并在此过程中决定将函数组件重构为类组件。这背后的原因,如果我错了,请纠正我的是TopNavSub
组件从react router 4
this.props.match.params.<var>
获取信息并选择要呈现的内容。
/mac
只会映射mac
数组等中的项目。
我被告知直接在this.props
内使用this.state
是一个糟糕的选择,而是使用componentWillReceiveProps()
,但React团队似乎对此感到不满,UNSAFE_componentWillReceiveProps(),但它没有解决任何问题。
TLDR;
所以这里的问题是在重构之后,我的数据只显示第一条初始路线,无论之后选择哪条路线,只会显示所选择的初始路线数据,除非刷新(f5
)。
import React, { Component } from 'react';
// data
import { subNavLinks } from './navigationData';
class TopNavSub extends Component {
constructor(props) {
super(props);
this.state = {
navLinks : { ...subNavLinks },
product : this.props.match.params.product,
currentProduct : Object.keys(subNavLinks).filter(subNavLinksKey => subNavLinksKey === this.props.match.params.product),
}
}
render() {
return (
(!this.state.navLinks)
?
null
:
<ul>
{
this.state.navLinks[this.state.product].map(product => {
return (
<li key={ product }>{ product }</li>
)
})
}
</ul>
)
}
};
export default TopNavSub;
export const subNavLinks = {
mac: ['MacBook', 'MacBook Air', 'MacBook Pro', 'iMac', 'iMac Pro', 'Mac Pro', 'Mac Mini', 'Accessories', 'High Sierra', 'Compare'],
ipad: ['iPad Pro', 'iPad', 'iPad Mini 4', 'iOS 11', 'Accessories', 'Compare'],
iphone: ['iPhone X', 'iPhone 8', 'iPhone 7', 'iPhone 6s', 'iPhone SE', 'iOS 11', 'Accessories', 'Compare'],
watch: ['Apple Watch 3', 'Apple Watch Nike+', 'Apple Watch Hermes', 'Apple Watch Edition', 'Apple Watch 1', 'Watch OS', 'Bands', 'Accessories', 'Compare'],
tv: ['Apple TV 4k', 'Apple TV', 'TV App', 'Accessories', 'Compare'],
music: ['Apple Music', 'iTunes', 'HomePod', 'iPod Touch', 'Music Accessories', 'Gift Cards'],
support: ['Apple doesn\'t support anything older than iOS11']
};
答案 0 :(得分:1)
您可以使用Any
解决问题,或者,如果您希望使用新的静态componentWillReceiveProps
,则可以解决问题。
getDerivedStateFromProps
<强>更新强>
关于第二个问题,一个好的一般规则是,如果您不需要处理用户输入事件或保存外部数据(例如来自后端API的数据),那么(&#34;&#34; &#34;可能&#34;&#34;&#34;)不需要组件状态。在这种情况下,您从props中获取整个状态而不进行任何事件处理,因此您可以将此组件简单地编写为如下函数:
class TopNavSub extends Component {
constructor(props) {
super(props);
//This could be extracted to avoid repetition, I'm copy-pasting it
const currentProduct = Object.keys(subNavLinks)
.filter(subNavLinksKey => subNavLinksKey === this.props.match.params.product);
this.state = {
navLinks: subNavLinks[currentProduct[0]],
product: this.props.match.params.product,
currentProduct
}
}
//IMPORTANT: USE EITHER ONE OR THE OTHER
//I wrote both options for demonstration purposes
componentWillReceiveProps(nextProps, prevState) {
const currentProduct = Object.keys(subNavLinks)
.filter(subNavLinksKey => subNavLinksKey === nextProps.match.params.product);
this.setState({
product: nextProps.match.params.product,
navLinks: subNavLinks[currentProduct[0]],
currentProduct
});
}
static getDerivedStateFromProps(nextProps, prevState) {
const currentProduct = Object.keys(subNavLinks)
.filter(subNavLinksKey => subNavLinksKey === nextProps.match.params.product);
return {
product: nextProps.match.params.product,
navLinks: subNavLinks[currentProduct[0]],
currentProduct
};
}
render() {
return (
(!this.state.navLinks)
?
null
:
<ul>
{
this.state.navLinks.map(product => {
return (
<li key={product}>{product}</li>
)
})
}
</ul>
)
}
};