简体   繁体   English

React UseEffect 在页面刷新时不起作用

[英]React UseEffect not working on page refresh

I am using a useEffect to fetch information from my backend api.我正在使用 useEffect 从我的后端 api 获取信息。 I am using Redux and I dispatch action on useeffect.我正在使用 Redux 并在 useeffect 上调度操作。 At first, It works but after page reloads all information become null and i get this error TypeError: Cannot read property 'mainImage' of null.起初,它可以工作,但在页面重新加载后,所有信息都变为 null,我收到此错误 TypeError: Cannot read property 'mainImage' of null。 In redux dev tools, it doesnot even call the action and my redux store state it is null.在 redux 开发工具中,它甚至都没有调用该操作,而我的 redux 存储 state 它是 Z37A6259CC0C1DAE2B9877A66498。 What could be possible error?什么可能是错误? My other components are working fine, even after reloading page and I am using same method in other components also.我的其他组件工作正常,即使在重新加载页面后我也在其他组件中使用相同的方法。 I have even checked if my response data are loading or not.我什至检查了我的响应数据是否正在加载。 I even console.log('HI') in useeffect and it doesnot show我什至 console.log('HI') 在使用效果,它没有显示

Here is my that component这是我的那个组件

const ProductDetailScreen = ({match,history}) => {
    
    
    const dispatch = useDispatch();
    const {loading,product,error}= useSelector(state=> state.singleProduct)
    
    
   useEffect(()=>{
      dispatch(getProductDetails(match.params.id))
   },[dispatch,match])

   
        
    return (
            
        <div className='my-5 p-3'>
             <Button variant="outline-dark" onClick={()=> history.push('/')}>
         <i className="fas fa-arrow-left"></i> Go Back
        </Button> 
        
        {loading ? <Loader/> : error? <AlertMessage>{error}</AlertMessage>:
        (
            <>
            <Row className='my-4'>
            <Col md={4}>
                <Image style={{width:'90%',height:'auto'}} alt='' fluid src={product.mainImage}/>
            </Col>

            <Col md={4}>
            <ListGroup variant='flush'>
                <ListGroup.Item>
                    <h3>{product.name}</h3>
                </ListGroup.Item>
                <ListGroup.Item>
                    <Rating value={product.ratings} text={`${product.numReviews} reviews`}/>
                </ListGroup.Item>
                <ListGroup.Item>
                    Quantity: {product.quantity}
                </ListGroup.Item>
                <ListGroup.Item>
                    Buyers: {product.sale}
                </ListGroup.Item>
                <ListGroup.Item>
                    <h5>Choose Version :</h5>
                   <ListGroup horizontal>
                   <Row>
                       {product.version.map(pro=>(
                            <Col key={pro._id} className='my-2 d-flex align-items-stretch' md={6}>
                            <ListGroup.Item>
                             <Form.Check defaultChecked type="radio" inline name="group1"  aria-label="radio 1" />
                             <h6>Version: {pro.version}</h6>
                             <h6>Price: ${pro.price}  </h6>
                            </ListGroup.Item>
                            </Col>
                       ))}
                      </Row>
                   </ListGroup>
                </ListGroup.Item>
                 </ListGroup>
                  </Col>
                  </Row>
                  </>
export default ProductDetailScreen

My reducer我的减速机

export const getProductFromID = (state={product:null},action)=>{
    switch(action.type){
        default:
        return state

        case GET_PRODUCT_REQUEST:
            return {loading:true}
        case GET_PRODUCT_SUCCESS:
            return{loading:false, product:action.payload}
        case GET_PRODUCT_FAIL:
            return {loading:false,error:action.payload}
    }
}

My store我的店铺

const rootReducer= combineReducers({
    productsReducer: getProductsReducer,
    topProducts: getTopProductReducer,
    categories: getCategoriesReducer,
    productCategories : getProductFromCategories,
    singleProduct: getProductFromID
})

const initialState ={};

const middleWare = [thunk];

const store = createStore(rootReducer,initialState, composeWithDevTools(applyMiddleware(...middleWare)))

export default store

My action creator我的动作创造者

export const getProductDetails = (id) => async (dispatch) => {
    try {
        dispatch({
            type: GET_PRODUCT_REQUEST
        })

        const res = await axios.get(`/api/products/${id}`)

        dispatch({
            type: GET_PRODUCT_SUCCESS,
            payload: res.data
        })

    } catch (error) {
        dispatch({
            type: GET_PRODUCT_FAIL,
            payload: error.response && error.response.data.message ? error.response.data.message : error.message
        })
    }
}

There is nothing wrong in my backend api, It works correctly in postman我的后端 api 没有任何问题,它在 postman 中正常工作

When you reload your page, your redux state is reset and hence during the first render, your product value is null and you are trying to access mainImage from product which breaks the flow of the page.当您重新加载页面时,您的 redux state 将被重置,因此在第一次渲染期间,您的产品值为 null 并且您正尝试从产品访问mainImage页面,这会中断。

To solve this, set the initial state in your reducer to have loading as true要解决此问题,请将减速器中的初始 state 设置为加载为 true

export const getProductFromID = (state={product:null, loading: true},action)=>{
    switch(action.type){
        default:
        return state

        case GET_PRODUCT_REQUEST:
            return {loading:true}
        case GET_PRODUCT_SUCCESS:
            return{loading:false, product:action.payload}
        case GET_PRODUCT_FAIL:
            return {loading:false,error:action.payload}
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM