Я сделал образец сайта электронной коммерции для практики и использовал React, Redux и Router-DOM. Впервые все загружается отлично. у него есть два маршрута ScreenShot-Link . Маршрут Home приводит меня на главную страницу, где возникает проблема, а маршрут Upload переводит меня на страницу загрузки. Но когда я снова go возвращаюсь к HomeRoute , данные, которые были извлечены из API , вместо этого не повторно визуализируют состояние удваивается. Я имею в виду, что существующее состояние остается неизменным, но по какой-то причине данные снова выбираются, а элементы визуализируются 2 раза ScreenShot-2-Link .
Элемент Body, который удваивается, если я возвращаюсь к нему с другого маршрута ...
const Body = ({getProducts, deleteProduct, productState})=>{
const {products, loading, error} = productState;
useEffect(()=>{
getProducts()
}, [getProducts])
const deleteProducts = (id)=>{
deleteProduct(id)
}
return (
<div className="display-flex width-full flex-wrap justify-content-center">
{!loading && !error && products?products.map(product=>(
product.data?product.data.map(d=>(
<BodyDiv
key={uuid.v4()}
imgSrc={d.imgSrc}
title={d.title}
details={d.details}
description={d.description}
onClick={()=>deleteProducts(d._id)}
/>
)):product.map(d=>(
<BodyDiv
key={uuid.v4()}
imgSrc={d.imgSrc}
title={d.title}
details={d.details}
description={d.description}
onClick={()=>deleteProducts(d._id)}
/>
))
))
: loading&&!error
? <div className="vertical-center-strict horizontal-center-strict">Loading.......</div>
: <div className="vertical-center-strict horizontal-center-strict">No Internet!</div>
}
</div>
)
}
const BodyDiv = (props)=>{
return(
<div className="container-div width-full card tiny-padding align-self-start">
<img title={props.title} className="img-responsive hover-filter" src={props.imgSrc}/>
<h2 className="text-align-center">{props.title}</h2>
<h5>{props.details}</h5>
<p className="text-align-justify">{props.description}</p>
<button
className="btn btn-danger"
onClick={props.onClick}
>Delete</button>
</div>
)
}
BodyDiv.propTypes = {
title: PropTypes.string.isRequired,
img: PropTypes.string,
details: PropTypes.string.isRequired,
description: PropTypes.string,
onClick: PropTypes.func
}
const mapStateToProps = (state)=>({
productState: state.productState
})
const conn = connect(mapStateToProps, {getProducts, deleteProduct})(Body)
export default conn;
Компонент маршрутизатора и компонент Nav
//Parent Router Comonent
const App = () => {
return (
<Router>
<AppNavBar />
<Switch>
<Route path="/" exact>
<Body />
</Route>
<Route path="/upload">
<Upload />
</Route>
<Route path="*">
<div className="vertical-center-strict top-20">
<h1 className="text-align-center">404</h1>
<h3>Page doesn't exist</h3>
<p>Please give the correct address!</p>
</div>
</Route>
</Switch>
</Router>
);
};
export default App;
//NavLink Components..
const NavBar = ()=>{
return(
<>
<NavLink activeClassName="link" to="/" exact>
<NavItem content="Home" /> //<a> element with content as a prop
<NavLink>
<NavLink activeClassName="link" to="/upload">
<NavItem content="Upload"
</NavLink>
</>
)
}
}
Мой код Redux: Магазин и редукторы
//Store
import {createStore, applyMiddleware} from "redux"
import rootReducer from "./reducers/index"
import thunk from "redux-thunk"
const middleWare = [thunk]
const store = createStore(rootReducer, applyMiddleware(...middleWare))
export default store
//RootReducer
import {
FETCHED_PRODUCTS,
FETCHING_PRODUCTS,
ERROR_GET_PRODUCTS,
DELETED_PRODUCT,
ERROR_DELETING_PRODUCT
} from "../actions/productActions";
const initialState = {
products: [],
loading: true,
error: false,
};
const productReducer = (state = initialState, action) => {
switch (action.type) {
case FETCHING_PRODUCTS:
return {
...state,
loading: true,
};
case FETCHED_PRODUCTS:
return {
...state,
products: state.products.concat(action.payload),
loading: false,
error: false,
};
case ERROR_GET_PRODUCTS:
return {
...state,
loading: false,
};
case DELETED_PRODUCT:
return {
...state,
products: state.products.map((product) =>
product.data.filter((d) => d._id !== action.payload)
),
error: false,
};
case ERROR_DELETING_PRODUCT:
return {
...state,
error: true,
};
default:
return state;
}
};
export default productReducer;
ActionCreators
export const getProducts = (payload)=>(dispatch)=>{
return(
fetch("/api/products")
.then(res=>{
dispatch({
type:FETCHING_PRODUCTS
})
if(!res.ok){
dispatch({
type: ERROR_GET_PRODUCTS
})
}
return res.json();
})
.then(json=>{
if(json)dispatch({
type: FETCHED_PRODUCTS,
payload: json
})
})
.catch(err=>{
console.log("Error!! failed to fetch data: "+ err)
})
)
}
export const deleteProduct = (payload)=>dispatch=>{
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
var requestOptions = {
method: 'DELETE',
headers: myHeaders,
body: JSON.stringify({"_id": payload}),
redirect: 'follow'
};
fetch("/api/product-delete", requestOptions).then(res=>{
dispatch({
type: DELETED_PRODUCT,
payload
})
if(res.status === 501 || res.status === 403){
dispatch({
type: ERROR_DELETING_PRODUCT,
})
}
})
.catch(err=>{
console.log("Failed to Delete")
})
}
Пожалуйста, помогите мне Я искал решение в течение 4 часов ... Было бы здорово, если бы вы помогите мне ... Заранее спасибо