Компонент повторно отрисовывается после нажатия на ссылку NavLink и загружает одни и те же данные несколько раз - PullRequest
0 голосов
/ 29 мая 2020

Я сделал образец сайта электронной коммерции для практики и использовал 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 часов ... Было бы здорово, если бы вы помогите мне ... Заранее спасибо

1 Ответ

1 голос
/ 29 мая 2020

При использовании ловушки useEffect вторым параметром являются зависимости ... поэтому он вызывает функцию снова, если зависимости изменяются. Поскольку getProducts - это функция, она больше никогда не будет вызвана. Вместо этого вы должны ввести products in there

useEffect(()=>{
        getProducts()
    }, [products])
//will refetch data everytime product state is updated.

Немного сложно увидеть, что происходит в коде. Но подозреваю, что проблема в этом. В противном случае дайте мне знать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...