javascript - 当 react 路由器路由更改时,类组件不会重新渲染

标签 javascript reactjs react-router react-router-dom

我有一个与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组件渲染第一个匹配的 RouteRedirect成分。您通常希望按照路径特定性的相反顺序对路由进行排序,即更多特定路径在更少之前具体路径。这样就无需指定 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/

相关文章:

javascript - HTML 中的内联 Javascript 无法加载

javascript - 我的 jquery 自动完成功能不起作用

java - 访问在不同浏览器窗口中运行的 Applet

javascript - 使用带有异步获取变量的 react-apollo 调用 graphql 查询

javascript - 这个 reducer 是否符合 Redux 规则?

reactjs - 如何防止用户返回 ReactJs 中的登录路由?

javascript - 使用 JavaScript 下载图像

reactjs - react 原生 jest.preset.js 文件丢失错误

javascript - 使用 React v4 进行子路由?

javascript - 从重定向标签返回 - React Router