简体   繁体   English

React Navigation Filter 仅在返回主屏幕时有效

[英]React Navigation Filter only works when going back to the home screen

within my React ecommerce store, I have navigation links that take you to the products filtered by whichever link you selected.在我的 React 电子商务商店中,我有导航链接,可将您带到由您选择的任何链接过滤的产品。 There are also filter buttons within the product display.产品显示中还有过滤器按钮。 Everything works fine, however, the navigation links only work when I go back to the home page.一切正常,但是,导航链接仅在我返回主页时才有效。 Example.例子。 I can click on mens & it filters to mens items.我可以点击男装,它会过滤到男装。 Then I can go home and from there click on womens and it filters to womens items.然后我可以回家,然后从那里点击女性,它会过滤到女性物品。 However, if I click on mens and then click on womens items, I see the path change in the url to womens but the filtered products on mens.但是,如果我点击男装,然后点击女装,我会看到 url 中的路径更改为女装,但过滤后的产品是男装。

Here is a small sample of the code from the 3 components I believe are leading to this.:这是我认为导致此问题的 3 个组件的一小部分代码示例:

App.js应用程序.js

class App extends React.Component {
  state= {
    cart: []
  }

  updateCart = (cartItem) => {
    this.setState({cart: [...this.state.cart, cartItem]})
  }
  removeFromCart = (id) => {
    this.setState({cart: this.state.cart.filter(i => i.id !== id)})
  }
  render() {
    return (
    <div className="App">

<Router>
      <Navigation/> 
  <Routes>
  <Route path="/" element={<Home />} />
  <Route path="/men" element={ <ButtonMenu updateCart={this.updateCart} path={'men'}/>} />
  <Rou</Routes>
      <FooterNav/>
  </Router>te path="/women" element={ <ButtonMenu updateCart={this.updateCart} path={'women'}/>} /
 </div>
    )
  }
}

export default App;

Navigation.js

class Navigation extends Component{
    
 
  render(){
        return(<>
            
<div>
<nav className="navbar navbar-expand-lg  ">
  <div className="container-fluid">
    <a className="navbar-brand" href="#"><img src = {logo} alt="logo" width = "150rem"/></a>
    <button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <span className="navbar-toggler-icon"></span>
    </button>
    <div className="collapse navbar-collapse" id="navbarSupportedContent">
      <ul className="nav justify-content-center myNav " >
        <li className="nav-item">
          <Link className="nav-link active" aria-current="page" to="/">Home</Link>
        </li>
        <li className="nav-item">
        <Link className="nav-link " aria-current="page" to="/men">Men</Link>
        </li>
        <li className="nav-item">
        <Link className="nav-link " aria-current="page" to="/women">Women</Link>
        </li>
             </ul>
    </div>
  </div>
</nav>
</div>
              </>
        )
    }
}

export default Navigation;


ButtonMenu.js

export const  ProductList =[ 70+ objects with category of men, women...etc ]


const CATEGORIES = ['All', 'Men', 'Women', 'Jersey', "Hats",'Shirts', 'Accessories', 'Collectable', 'Top-Products', 'New-Arrivals'];

 


class ButtonMenu extends Component {
    constructor(props) {
      super(props);
      this.state = {
        products: ProductList
      };

    }
    

    getCategory = (category) => {
      if (category === "all") {
        this.setState({ products: ProductList });
      } else {
        const filter = ProductList.filter((d) => d.category === category);
        if (filter) {
          this.setState({ products: filter });
        }
      }
    };

    componentDidMount(){
   
        const path = this.props.path
        if (path === "all") {
        this.setState({ products: ProductList });
      } else {
        const filter = ProductList.filter((d) => d.category === path);
        if (filter) {
          this.setState({ products: filter });
        }
      }
    }

    render() {
      return (
        <>
          <div className="mainbtn-menu-container">
            
            {CATEGORIES.map((item, index) => (
                 <button
              key={index}
                className="main-btn"
                onClick={() => { this.getCategory(item.toLowerCase()) } }
                value={item.toLowerCase()}
              >
               {item} 
              </button> 
            ))}
            </div>

            <Products products={this.state.products} updateCart={this.props.updateCart} />
         
        </>
      );
    }
  }
  
  export default ButtonMenu;

The ButtonMenu component doesn't handle when props update to update any local state.当 props 更新以更新任何本地状态时, ButtonMenu组件不处理。 This would be handled by the componentDidUpdate lifecycle hook.这将由componentDidUpdate生命周期挂钩处理。 That said , it's considered anti-pattern to duplicate React state or store derived state.也就是说,复制 React 状态或存储派生状态被认为是反模式。 You can simply filter the ProductList array inline when rendering based on the path prop.在基于path属性进行渲染时,您可以简单地过滤ProductList数组。

Example:例子:

class ButtonMenu extends Component {
  state = {
    category: 'all',
  }

  render() {
    return (
      <>
        <div className="mainbtn-menu-container">
          {CATEGORIES.map((item, index) => (
            <button
              key={index}
              className="main-btn"
              onClick={() => this.setState({
                category: item.toLowerCase(),
              })}
              value={item.toLowerCase()}
            >
             {item} 
            </button> 
          ))}
        </div>

        <Products
          products={ProductList
            .filter(el => {
              if (this.state.category === 'all') {
                return true;
              }
              return el.category === this.state.category;
            })
            .filter(el => {
              if (this.props.path === 'all') {
                return true;
              }
              return el.gender === path;
            })
          }
          updateCart={this.props.updateCart}
        />
      </>
    );
  }
}

I suggest converting ButtonMenu to a function component and rendering a single route with a route param that can be read by the component.我建议将ButtonMenu转换为函数组件,并使用组件可以读取的路由参数渲染单个路由。

Example:例子:

<Router>
  <Navigation/> 
  <Routes>
    <Route path="/" element={<Home />} />
    <Route
      path="/:gender"
      element={<ButtonMenu updateCart={this.updateCart} />}
    />
  </Routes>
  <FooterNav/>
</Router>

... ...

import { useParams } from 'react-router-dom';

const ButtonMenu = ({ updateCart }) => {
  const { gender } = useParams();
  const [category, setCategory] = React.useState('all');

  return (
    <>
      <div className="mainbtn-menu-container">
        {CATEGORIES.map((item, index) => (
          <button
            key={index}
            className="main-btn"
            onClick={() => this.setCategory(item.toLowerCase())}
            value={item.toLowerCase()}
          >
           {item} 
          </button> 
        ))}
      </div>

      <Products
        products={ProductList
          .filter(el => {
            if (category === 'all') {
              return true;
            }
            return el.category === category;
          })
          .filter(el => {
            if (gender === 'all') {
              return true;
            }
            return el.gender === gender;
          })
        }
        updateCart={updateCart}
      />
    </>
  );
}

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM