英文:
Data fetching not happening when I use two parameters in React Router Dom and navigate directly on the page
问题
I will only translate the code portions you provided. Here's the translation:
我在React Router中遇到了一个非常奇怪和复杂的问题。我试图实现一个单页面应用,页面数量取决于JSON文件中的产品数量。
在我的应用中,我有一个主页面,它始终只包含一个页面,因此只有一个参数,称为:section。我遇到的问题仅在我使用第二个参数:page_number时发生,所有其他页面都有这个参数。
这是我的主要组件,包含各种页面,并依赖于路由参数:
```jsx
import { Routes, Route } from 'react-router-dom';
import GoodsList from './GoodsList';
import Pages from './Pages';
function Sections() {
return (
<Routes>
<Route path='' element={
<>
<div className="pageContent" data-main="true">
<p>Novelties</p>
<GoodsList goods="novelties" />
<p>Hot</p>
<GoodsList goods="hot" />
</div>
</>
} />
<Route path='/:section/:page_number' element={
<>
<div className='pageContent'>
<GoodsList />
<Pages />
</div>
</>
} />
</Routes>
)
}
我使用这个组件来导航到页面:
import { Link } from 'react-router-dom';
function Menu() {
return (
<nav className='menu'>
<ul>
<li>
<Link to="">Main</Link>
</li>
<li>
<Link to="figures/1">Figures</Link>
</li>
<li>
<Link to="dakimakuras/1">Figures</Link>
</li>
<li>
<Link to="manga/1">Manga</Link>
</li>
<li>
<Link to="other/1">Other merch</Link>
</li>
</ul>
</nav>
)
}
最后,这个组件显示产品列表:
import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { fetchProducts } from '../redux/fetchDataReducer';
import { useParams } from 'react-router-dom';
function GoodsList(props) {
const params = useParams();
const goods = returnGoods();
function returnGoods() {
if (document.location.pathname === "/") {
return props.goods;
}
return params.section;
}
const dispatch = useDispatch();
useEffect(() => {
dispatch(fetchProducts());
}, []);
const products = useSelector(state => state.fetchDataReducer.products);
return (
<div className="list">
{products && products[goods].map((good, i) => (
<div className="productCard" key={i}>
<div className="productPicture">
<img src={good.pic} alt="ERROR" />
</div>
<p className="productName">{good.name}</p>
</div>
))}
</div>
)
}
如果您需要更多帮助,请告诉我。
英文:
I faced a really strange and complex problem with React Router. I am trying to implement a single page application with a varying number of pages that depends on the number of products in the json file.
In my app I have the main page that always consist only of one pages thus it has only one paramater which is called :section. The bug I'm stuck with happens only when I use the second parameter :page_number, all other pages have this parameter.
This is my main component that contains various pages and depends on the router params
import { Routes, Route } from 'react-router-dom';
import GoodsList from './GoodsList';
import Pages from './Pages';
function Sections() {
return (
<Routes>
<Route path='' element={<>
<div className="pageContent" data-main="true">
<p>Novelties</p>
<GoodsList goods="novelties" />
<p>Hot</p>
<GoodsList goods="hot" />
</div>
</>} />
<Route path='/:section/:page_number' element={<>
<div className='pageContent'>
<GoodsList />
<Pages />
</div>
</>} />
</Routes>
)
This component I use for navigation on the page
import { Link } from 'react-router-dom';
function Menu() {
return (
<nav className='menu'>
<ul>
<li>
<Link to="">Main</Link>
</li>
<li>
<Link to="figures/1">Figures</Link>
</li>
<li>
<Link to="dakimakuras/1">Figures</Link>
</li>
<li>
<Link to="manga/1">Manga</Link>
</li>
<li>
<Link to="other/1">Other merch</Link>
</li>
</ul>
</nav>
)
}
And finaly this component displays the list of products
import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { fetchProducts } from '../redux/fetchDataReducer';
import { useParams } from 'react-router-dom';
function GoodsList(props) {
const params = useParams();
const goods = returnGoods();
function returnGoods() {
if (document.location.pathname == "/") {
return props.goods
}
return params.section
}
const dispatch = useDispatch();
useEffect(() => {
dispatch(fetchProducts());
}, [])
const products = useSelector(state => state.fetchDataReducer.products);
return (
<div className="list">
{products && products[goods].map((good, i) => (
<div className="productCard" key={i}>
<div className="productPicture">
<img src={good.pic} alt="ERROR" />
</div>
<p className="productName">{good.name}</p>
</div>
))}
</div>
)
}
The thing is when I click on the main page in the nav bar or move to it directly by typing the path in the address bar it always works fine. Then if I click on any section in the nav bar everything works fine either, BUT if I will try to refresh the page or move to any of the pages except the main by directly typing its address in the bar the GoodsList component won't load the products list. The fetching of data won't happen somehow, but the component itself and all the parameters from the address bar will be loaded fine. BUT if I will move to the main page again and then to any other section by using the nav Link it will be loaded fine again and the problem won't appear till I refresh the page.
So, the problem appears only if I have the :page_number parameter and affects only the data I recieve from json file through Redux. If I delete this second parameter the bug won't happen. It happens when I move to any section with this parameter directly or refresh the page, if I use navigation links on my menu bar it works fine but ONLY if I visited the main page before that.
UPD. Adding the pages component
import { useSelector } from "react-redux";
import { Link, useParams } from 'react-router-dom';
function Pages() {
const params = useParams();
const products = useSelector(state => state.fetchDataReducer.products);
const currentProduct = products ? products[params.section] : [];
const pageLinks = [];
let numberOfPages = () => {
if ((currentProduct.length / 8) % 1 == 0) {
return currentProduct.length / 8
}
else return Math.floor((currentProduct.length / 8) + 1)
}
for (let x = 1; x < (numberOfPages() + 1); x++) {
pageLinks.push(<Link to={`/${params.section}/${x}`} className="pageLink" key={x}>{x}</Link>);
}
return (
<div className="pageList">
{pageLinks}
</div>
)
}
答案1
得分: 1
The fetchProducts
action is currently using a relative resource path for the products.json
file it's fetching from the /public
directory.
fetch("products.json")
This works when the app is on the root /
route, but when navigating to sub-routes like /:section/:page_number
, it requests "/figures/1/products"
which doesn't exist in the public directory. To fix this, use an absolute resource path like "/products.json"
.
fetch("/products.json")
Here's the relevant code snippet:
export const fetchProducts = createAsyncThunk(
"dataFetch/fetchProducts",
async () => {
const response = await fetch("/products.json");
const data = await response.json();
return data;
}
);
英文:
The fetchProducts
action is using a relative resource path for the products.json
file it's fetching/loading from the "/public"
directory.
fetch("products.json")
This works fine and as expected when the app is currently sitting on the root "/"
route rendering the GoodsList
component when is dispatches fetchProducts
. The products.json
resource is requested relative to the current URL path, e.g. "/products.json"
and the data is loaded into the Redux store without issue.
Upon navigating to the sub-route, e.g. "/:section/:page_number"
, the products.json
file is now requested relative to that path, e.g. "/figures/1/products"
which doesn't exist in the public directory. When the user is on a sub-route and reloads the page, the fetch just fails. This is fine so long as the user at least (eventually) lands on the main "/"
page so when the request is made it actually succeeds.
To resolve you can simply specify an absolute resource path to "/products.json"
.
fetch("/products.json")
export const fetchProducts = createAsyncThunk(
"dataFetch/fetchProducts",
async () => {
const response = await fetch("/products.json");
const data = await response.json();
return data;
}
);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论