简体   繁体   English

当反应路由器路由更改时,class 组件不会重新渲染

[英]class component doesn't re-render when react router route changes

I have a question related to react-router and class components in React this is the first time I use class components in an app and I kind of get confused with lifecycle methods我有一个与 React 中的 react-router 和 class 组件有关的问题,这是我第一次在应用程序中使用 class 组件,我有点对生命周期方法感到困惑

my issue is I have a component where I display products in this component I switch categories of products where I do filter when switching as the API doesn't provide each category with its product so now I switch using react-router and I do change the route to "/category/:nameOfCategory" when I click on the link of tech products in the address bar it changes but the component doesn't re-render as the props are not updating or refreshing this is where I do the request我的问题是我有一个组件,我在该组件中显示产品我切换了我在切换时进行过滤的产品类别,因为 API 没有为每个类别提供其产品,所以现在我使用 react-router 进行切换,我确实将路线更改为"/category/:nameOfCategory"当我点击地址栏中的科技产品链接时,它会改变,但组件不会重新渲染,因为道具没有更新或刷新这是我提出请求的地方

 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>
    );
  }
}

This is the route in App.js这是 App.js 中的路由

<Router>
      <Navbar
     
      />
      <Switch>
        <Route
          exact
          path="/"
        
        >
          <Redirect to="/category/all"  />
        </Route>
        <Route path="/category/:name"  component={CategoryPage}/>
      
      </Switch>
    </Router>

Issue问题

The component correctly handles checking the routes params when the component mounts, but not when it rerenders when the params change.组件在安装组件时正确处理检查路由参数,但在参数更改时重新渲染时不会。

Solution解决方案

Implement the componentDidUpdate lifecycle method to make the same request.实现componentDidUpdate生命周期方法以发出相同的请求。 To make the code more DRY you'll want to factor the request logic into a utility function.为了使代码更干燥,您需要将请求逻辑分解到实用程序 function 中。

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();
  }
}

Note: There is an issue with react@18 's StrictMode component and earlier versions of react-router-dom@5 .注意: react@18StrictMode组件和早期版本的react-router-dom@5存在问题。 If this effects you then you should update to at least react-router-dom@5.3.3 .如果这影响到你,那么你应该至少更新到react-router-dom@5.3.3 See this answer for more details.有关更多详细信息,请参阅此答案

Suggestions建议

It is considered a bit of an anti-pattern to store derived state in React state.在 React state 中存储派生的 state 被认为是一种反模式。 The derived state here is the filtered result of applying that name parameter against the fetched data.此处派生的 state 是将name参数应用于获取的数据的过滤结果。 Instead of fetching all the data any time the filtering parameters change, you could fetch once when the component mounts and handle filtering inline when rendering.您可以在组件安装时获取一次并在渲染时处理内联过滤,而不是在过滤参数更改时获取所有数据。

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>
  );
}

As a code improvement you can simplify the routing code a little bit.作为代码改进,您可以稍微简化路由代码。 Within the Switch component route path order and specificity matters.Switch组件内,路由路径顺序和特异性很重要。 The Switch component renders the first matching Route or Redirect component. Switch组件呈现第一个匹配的RouteRedirect组件。 You'll generally want to order the routes in inverse order of path specificity, ie more specific paths before less specific paths.您通常希望以路径特异性的相反顺序对路线进行排序,即具体的路径在不太具体的路径之前。 This eliminates the need to specify the exact prop.这消除了指定exact道具的需要。

The Redirect component also takes a from prop which is path you want to redirect from. Redirect组件接受一个from道具,它是您要重定向的路径。

<Router>
  <Navbar />
  <Switch>
    <Route path="/category/:name" component={CategoryPage} />
    <Redirect from="/" to="/category/all" />
  </Switch>
</Router>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 状态更改时,React组件不会重新呈现 - React component doesn't re-render when state changes 当上下文状态改变时,React 钩子上下文组件不会重新渲染 - React hooks context component doesn't re-render when context state changes 当 prop 更改时,React 功能组件不会重新渲染 - React functional component doesn't re-render when prop changes 为什么这个 React 组件在其 prop 更改时不重新渲染? - Why doesn't this React component re-render when its prop changes? React:如何有效地制作我的组件,以便在道具更改时整个组件不会重新渲染? - React: How can I efficiently make my component so the entire component doesn't re-render when a prop changes? 当主线程与其他操作排队时,state 更改后 React 不会重新渲染组件? - React doesn't re-render component after state changes when main thread is queued up with other operations? 反应路由器更改 url 但不重新渲染 - React router changes url but not re-render 当状态改变时,React 不会重新渲染组件 - React does not re-render component when the state changes 查询字符串更改时重新呈现React组件 - Re-render React Component when query string changes 属性更改时如何重新渲染React组件 - How to re-render react component when a property changes
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM