React-router вместе с Redux
Нужна ваша помощь. Я беру данные с API и отрисовываю их. Также я пытаюсь сделать переход на каждый отдельный продукт с помощью React-router. Но переход у меня не происходит, а в url у меня постоянно добавляется / products. Как сделать нормальный переход на компонента Product Detail? Спасибо
Products.js
import React, {useEffect, useState} from "react";
import {useDispatch, useSelector} from "react-redux";
import {products_are_loaded} from "../Redux/Action_creators";
import {Link, Route, BrowserRouter as Router} from "react-router-dom";
import {Product_Detail} from "./Product_Detail";
export let Products = () => {
let dispatch = useDispatch();
let all_products = useSelector(({products_reducer : {all_products}}) => all_products)
let fetchProducts = async () => {
try {
let response = await fetch('https://fakestoreapi.com/products');
let json = await response.json();
console.log(json)
dispatch(products_are_loaded(json));
} catch (error) {
console.log(error);
}
}
useEffect(() => {
fetchProducts()
},[])
return (<Router>
<div className="products_page">
{all_products.map(el =>
<div key={el.id} className="different_product">
<div>
<Link to={`products/${el.id}`}><p>{el.title}</p></Link>
</div>
<div> <img src={el.image} className="product_image"/> </div>
<div> <button>Add to cart</button> </div>
</div>)}
</div>
</Router>)
}
Product_detail.js
import React, {useEffect} from "react";
import {useParams} from "react-router-dom";
import {useDispatch, useSelector} from "react-redux";
import {different_product_are_loaded} from "../Redux/Action_creators";
export let Product_Detail = () => {
let {id} = useParams();
let dispatch = useDispatch();
let product_details = useSelector(({products_reducer : {different_product}}) => different_product);
let fetchProductDifferent = async () => {
try {
let response = await fetch(`https://fakestoreapi.com/products/${id}`)
let json = await response.json();
dispatch(different_product_are_loaded(json));
} catch (error) {
console.log(error);
}
}
useEffect(() => {
fetchProductDifferent()
},[])
return (<div>Product Details</div>)
}
App.js
import './App.css';
import {All_products} from "./Components/All_products";
import {Cart} from "./Components/Cart";
import {Link, Route, BrowserRouter as Router} from "react-router-dom";
import {Product_Detail} from "./Components/Product_Detail";
function App() {
return (<Router>
<div>
<header className="header">
<Link to={'/cart'}>Go to my cart</Link>
<br/>
<Link to={'/products'}>All products</Link>
</header>
<Route path={'/cart'} component={Cart}/>
<Route path={'/products'} component={All_products}/>
<Route path={'/products/:id'} component={Product_Detail}/>
</div>
</Router>);
}
export default App;
Ответы (1 шт):
Чтобы в url постоянно не добавлялся /products необходимо добавить / в начале пути:
<Link to={`/products/${el.id}`}><p>{el.title}</p></Link>
Соответственно нужен слэш и в Route:
<Route path="/products/:id" component={Product_Detail}/>
Так же внёс некоторые изменения: Теперь можно заходить на продукты и по ссылке на продукт открываются детали продукта. Добавил кнопку назад. Вот изменения:
All_products.js:
import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { products_are_loaded } from "../Redux/Action_creators";
import { Link } from "react-router-dom";
export let All_products = () => {
let dispatch = useDispatch();
let all_products = useSelector(
({ products_reducer: { all_products } }) => all_products
);
let fetchProducts = async () => {
try {
let response = await fetch("https://fakestoreapi.com/products");
let json = await response.json();
console.log(json);
dispatch(products_are_loaded(json));
} catch (error) {
console.log(error);
}
};
useEffect(() => {
fetchProducts();
}, []);
return (
<div className="products_page">
{all_products.map((el) => (
<div key={el.id} className="different_product">
<Link to={`/products/${el.id}`}>
<p>{el.title}</p>
{el.id}
</Link>
<img src={el.image} className="product_image" />
<button>Add to cart</button>
</div>
))}
</div>
);
};
Product_Detail.js
import React, { useEffect } from "react";
import { useParams, useHistory } from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";
import { different_product_are_loaded } from "../Redux/Action_creators";
export const Product_Detail = () => {
const { id } = useParams();
const dispatch = useDispatch();
const history = useHistory();
const { title, description } = useSelector(
(state) => state.products_reducer.different_product
);
const fetchProductDifferent = async () => {
try {
const response = await fetch(`https://fakestoreapi.com/products/${id}`);
const json = await response.json();
dispatch(different_product_are_loaded(json));
} catch (error) {
console.log(error);
}
};
useEffect(() => {
fetchProductDifferent();
}, []);
const goBackHandler = () => {
history.goBack();
};
return (
<div>
<h1>Product {id} Detail</h1>
<div>Title: {title}</div>
<div>Description: {description}</div>
<button onClick={goBackHandler}> Go Back</button>
</div>
);
};
App.js
import "./App.css";
import { All_products } from "./Components/All_products";
import { Cart } from "./Components/Cart";
import { Link, Route, BrowserRouter as Router } from "react-router-dom";
import { Product_Detail } from "./Components/Product_Detail";
function App() {
return (
<Router>
<div>
<header className="header">
<Link to={"/cart"}>Go to my cart</Link>
<br />
<Link to={"/products"}>All products</Link>
</header>
<Route path={"/cart"} component={Cart} />
<Route path={"/products/:id"} component={Product_Detail} />
<Route exact path={"/products"} component={All_products} />
</div>
</Router>
);
}
export default App;
Так же залил на GitHub: https://github.com/KonstantinModin/temp2