Наличие побочного эффекта в виде умножения состояния компонента после каждого изменения маршрута - PullRequest
0 голосов
/ 30 мая 2020

Я делаю веб-приложение SPA для практических целей, но у меня проблемы с React Rendering. У моего приложения обычно только два рабочих маршрута Home & Upload . Home Route Получает данные из API и отображает их в компоненте Body ... С Upload Я могу загружать продукты в базу данных ... Все работает нормально, кроме домашней страницы ...

Когда я возвращаюсь в Home с другого маршрута, предыдущее состояние остается таким же, но по какой-то причине состояние умножается, а все просто удваивается, я имею в виду, что полученные данные удваиваются. . Пожалуйста, помогите мне ....

Компонент тела моего приложения, в котором отображаются полученные данные
//Importing Redux Action Creators
import {getProducts, deleteProduct} from "../Features/actions/productActions"
const Body = ({getProducts, deleteProduct, productState})=>{
    const {products, loading, error} = productState; //Destructuring redux State

     //Fetching data using redux actions inside useEffect hook
    useEffect(()=>{
    getProducts()
    },[getProducts])

    //Providing the payload as id for Redux Actions
    const deleteProducts = (id)=>{
        deleteProduct(id)
    }

    return (
        <div className="display-flex width-full flex-wrap justify-content-center">
            //Some Loading Logic for displaying data
            {!loading && !error && products?products.map(product=>(
                product.data?product.data.map(d=>(
                  //This is the component which displays the fetched data as bootstarp card
                    <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>
    )
}
//The layout for displaying fetched data
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>
    )   
} 
//mapping & dispatching state to props from redux
const mapStateToProps = (state)=>({
    productState: state.productState
})
//React-Redux Connect to connect the component with Store
const conn = connect(mapStateToProps, {getProducts, deleteProduct})(Body)

export default conn;
Создатели и редукторы действий в моем состоянии Redux
//Using redux-thunk for asynchronus middleware
export const getProducts = (payload)=>(dispatch)=>{
   return fetch("/api/products") //URL
    .then(res=>{
        dispatch({
            type:FETCHING_PRODUCTS //While fetching data
        })
        if(!res.ok){
            dispatch({
                type: ERROR_GET_PRODUCTS //If fetch fails then executes
            })
        }
    return res.json();
    })
    .then(json=>{
        if(json)dispatch({
        type: FETCHED_PRODUCTS,
        payload: json //Fetched json data as payload
    })
})
    .catch(err=>{
        console.log("Error!! failed to fetch data: "+ err)
    })
} 

//Reducer Function

//initial state
const initialState = {
  products: [], //this the state where Fetched data gets injected...
  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), //I don't know but I doubt here is the problem
        loading: false,
        error: false,
      };
    case ERROR_GET_PRODUCTS:
      return {
        ...state,
        loading: false,
      };
    default:
      return state;
  }
};

export default productReducer;

Я считаю, что что-то не так с хуком useEffect () или функцией редуктора .. Некоторые люди сказали бы, что я должен попробовать использовать продукты состояние как зависимость useEffect cie но это только усугубляет ситуацию ... Ребята, пожалуйста, помогите мне !!! Уже 1 день пытаюсь исправить ... Спасибо !!

1 Ответ

0 голосов
/ 30 мая 2020

Да, проблемы, похоже, там, где вы думаете

 return {
        ...state,
         // the problem is here, you are adding products when in reality you just be just replacing them
        products: state.products.concat(action.payload), //I don't know but I doubt here is the problem
        loading: false,
        error: false,
      };

замените это на

return {
        ...state,
        products: action.payload
        loading: false,
        error: false,
      };
...