我有一个与React中的react-router和类组件相关的问题,这是我第一次在应用程序中使用类组件,我对生命周期方法有点困惑
我的问题是我有一个组件,我在该组件中显示产品,我切换产品类别,在切换时进行过滤,因为 API 没有为每个类别提供其产品
所以现在我切换使用react-router,并且当我单击地址栏中的技术产品链接时,我确实将路由更改为 "/category/:nameOfCategory"
它会更改,但组件不会更改由于 Prop 没有更新或刷新而重新渲染
这是我提出请求的地方
componentDidMount() {
request("http://localhost:4000/", getItems).then((ItemsData) => {
if (this.props.match.params.name === "all") {
this.setState({ products: ItemsData.category.products });
} else {
const filtered = ItemsData.category.products.filter((products) => {
let filteredProducts;
if (products.category === this.props.match.params.name) {
filteredProducts = products;
}
return filteredProducts;
});
this.setState({ products: filtered });
}
});
}
render() {
const { match, location } = this.props;
console.log(this.props);
return (
<div>
<h1 className="category-heading">{match.params.name}</h1>
<div className="category-items">
{this.state.products.map((product) => {
return <ItemCard key={location.key} productData={product} />;
})}
</div>
</div>
);
}
}
这是App.js中的路由
<Router>
<Navbar
/>
<Switch>
<Route
exact
path="/"
>
<Redirect to="/category/all" />
</Route>
<Route path="/category/:name" component={CategoryPage}/>
</Switch>
</Router>
最佳答案
问题
该组件在组件安装时正确处理检查路由参数,但在参数更改时重新渲染时则不能。
解决方案
实现componentDidUpdate
生命周期方法发出相同的请求。为了使代码更加干燥,您需要将请求逻辑分解到实用函数中。
getData = () => {
const { match: { params } } = this.props;
request("http://localhost:4000/", getItems)
.then((ItemsData) => {
if (params.name === "all") {
this.setState({ products: ItemsData.category.products });
} else {
const filtered = ItemsData.category.products.filter((products) => {
let filteredProducts;
if (products.category === params.name) {
filteredProducts = products;
}
return filteredProducts;
});
this.setState({ products: filtered });
}
});
};
componentDidMount() {
this.getData();
}
componentDidUpdate(prevProps) {
if (prevProps.match.params.name !== this.props.match.params.name) {
this.getData();
}
}
注意: react@18
有问题的StrictMode
react-router-dom@5
的组件和早期版本。如果这对您有影响,那么您应该至少更新到 <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="7a081f1b190e5708150f0e1f08571e15173a4f54495449" rel="noreferrer noopener nofollow">[email protected]</a>
。看这个answer了解更多详情。
建议
在 React 状态中存储派生状态被认为是一种反模式。这里的派生状态是应用 name
的过滤结果针对获取的数据的参数。您可以在组件安装时获取一次数据,并在渲染时处理内联过滤,而不是在过滤参数发生变化时获取所有数据。
getData = () => {
const { match: { params } } = this.props;
request("http://localhost:4000/", getItems)
.then((data) => {
this.setState({ products: data.category.products });
});
};
componentDidMount() {
this.getData();
}
render() {
const { match: { params } } = this.props;
return (
<div>
<h1 className="category-heading">{match.params.name}</h1>
<div className="category-items">
{this.state.products
.filter(product => {
if (params.name !== 'all') {
return product.category === params.name;
}
return true;
})
.map((product) => (
<ItemCard key={product.id} productData={product} />
))}
</div>
</div>
);
}
作为代码改进,您可以稍微简化路由代码。 Switch
内组件路由路径顺序和特殊性很重要。 Switch
组件渲染第一个匹配的 Route
或Redirect
成分。您通常希望按照路径特定性的相反顺序对路由进行排序,即更多特定路径在更少之前具体路径。这样就无需指定 exact
Prop 。
Redirect
组件也采用 from
prop 这是您要重定向的路径。
<Router>
<Navbar />
<Switch>
<Route path="/category/:name" component={CategoryPage} />
<Redirect from="/" to="/category/all" />
</Switch>
</Router>
关于javascript - 当 react 路由器路由更改时,类组件不会重新渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73871534/