UseEffect无法正常工作,并且还面临使用问题?

时间:2020-10-11 15:28:39

标签: reactjs react-native react-redux

我制作了一个像Amazon和Flipkart这样的应用程序,可以根据类别过滤产品。

import React, { useState,useEffect} from 'react'
import { FlatList,View,Image,Text,StyleSheet,TouchableOpacity,ActivityIndicator} from 'react-native';
import {useSelector , useDispatch} from "react-redux";
import ShopComponent from "../components/ShopComponent";
import * as cartActions from "../store/actions/Cart"
import * as ProductActions from "../store/actions/Product"
import {HeaderButtons,Item} from "react-navigation-header-buttons";
import HeaderButton from "../components/UI/HeaderComponent";
import Product from '../models/Product';
import ProductsList from "../data/DataTemp";
import SearchScreen from "./SearchScreen";






const SecondScreen =(props)=>{

  const [CurrentCategory, setCurrentCategory] = useState([]);   
    
      const category = props.navigation.getParam("title");
      const UpdatedCategory=useSelector(state =>
        state.Products.availableProduct.filter((product)=>{
          return product.category == category
          
        

        } )
      );
  
    
      const dispatch=useDispatch();
        
        
      useEffect(()=>{   
       
        setCurrentCategory(UpdatedCategory)            
      },[])

      useEffect(()=>{        
        dispatch(ProductActions.fetchProduct());         
      },[dispatch])   


const loadBooks = (itemData)=>{
   let newBook = {
     id : itemData.item.id,
     title : itemData.item.title,
     Description : itemData.item.Description,
     image : itemData.item.image,
     Price : itemData.item.Price,
     category : itemData.item.category,

   }
return (


<TouchableOpacity onPress={()=>{props.navigation.navigate("Detail", 
    { productId: itemData.item.id,
      productTitle:itemData.item.title } );
}}>
  
            
            
<View style={styles.productMain}>
           
    <View style={{width:"35%", height:200, }}>
          <Image style={{width : "100%" , height:"95%" , resizeMode:"contain", borderRadius:5}} 
            source={{uri : itemData.item.imageUrl}} />
    </View>

    <View style={{ justifyContent: "space-around", alignContent:"center",  marginLeft:40,}}>

        <View style={{overFlow:"hidden"}}>
           <Text numberOfLines={1} style={styles.text}>{itemData.item.title}</Text>
        </View>

        <View>
           <Text numberOfLines={1} style={styles.text}>Price : Rs {itemData.item.price}</Text>
           
        </View>
           

    </View>

</View>
</TouchableOpacity>
)

}

return (
      <View style={styles.main}> 
       <FlatList          
          data={CurrentCategory}
          keyExtractor={item => item.id}
          renderItem={loadBooks}         
  />
  </View>
  
)
}

SecondScreen.navigationOptions = navData=>{

   return{
   
   headerTitle:"Deep Mart",
   headerLeft:(()=><HeaderButtons HeaderButtonComponent={HeaderButton}>
   <Item title="ToggleDrawer" iconName={"md-menu" } onPress={()=>{navData.navigation.toggleDrawer();}}/>

 </HeaderButtons>

   ),
   headerRight:(()=><HeaderButtons HeaderButtonComponent={HeaderButton}>
   <Item title="cart" iconName={"md-cart" } onPress={()=>{navData.navigation.navigate("Cart")}}/>

 </HeaderButtons>

   ), }

};



const styles = StyleSheet.create({
main: {
  flex : 1,
  padding : 10,
 
},
bookMain :{
  marginTop:10,
  width : "100%",
  height:500,
 
  borderColor:"black" , 
  borderWidth:1,
  borderRadius : 5
},
productMain: {
flexDirection:"row", 
justifyContent:"flex-start", 
borderBottomWidth:1,
marginBottom:10,
backgroundColor:"white",
borderRadius:10,


  
},
text : {
  color:"black",
  fontSize: 15,
  fontWeight:"bold",
  overflow:"hidden",
 
}
});

export default SecondScreen;

在这里,我使用了两个useEffect 用于过滤基于类别的标题,和用于从商店中的ProductAction获取产品。

import Product from "../../models/Product";

 export const DELETE_PRODUCT = "DELETE_PRODUCTS";
 export const CREATE_PRODUCT="CREATE_PRODUCT";
 export const UPDATE_PRODUCT="UPDATE_PRODUCT";
 export const SET_PRODUCTS = "SET_PRODUCTS"
 export const SOLD_PRODUCTS = "SOLD_PRODUCTS"

 
 export const fetchProduct=()=>{
  return async dispatch => {
    // any async code you want!
    try {
      const response= await fetch("https://direp-marct.firebaseio.com/products.json");

      if (!response.ok) {
        throw new Error('Something went wrong!');
      }

      const resData = await response.json();
      const loadedproducts = [];

    
      for(const key in resData) {
        loadedproducts.push(
          new Product(
            key ,
            "u1",
        
            resData[key].title ,
            resData[key].imageUrl ,
            resData[key].description,
            resData[key].price,
             resData[key].mrp,
            resData[key].category
            )
            );
      }
      dispatch({ type: SET_PRODUCTS, products: loadedproducts });
    } catch (err) {
      // send to custom analytics server
      throw err;
    }
  };
};


 export const deleteProduct=(ProductId)=>{
   return async (dispatch) =>{
    

     fetch(`https://direp-marct.firebaseio.com/products/${ProductId}.json`,{
       method:"DELETE"
     });
      dispatch({type:DELETE_PRODUCT , pid:ProductId}) 

   }
  
 };
 export const soldProduct=(ProductId)=>{
   return async (dispatch) =>{
 
     fetch(`https://direp-marct.firebaseio.com/products/${ProductId}.json`,{
       method:"POST"
     });
      dispatch({type:DELETE_PRODUCT , pid:ProductId}) 

   }
  
 };

 export const createProduct=(title , description ,imageUrl, price , mrp ,category)=>{
  return async (dispatch)=>{ 
 , {
  const response= await fetch("https://direp-marct.firebaseio.com/products.json" , 
  {

      method:"POST",
      header:{
        "Content-Type":"Application/json"
      },
      body:JSON.stringify({
        title,
        description,
        imageUrl,
        price,
        mrp,
        category
      })
   });

   const resData = await response.json(); 


    dispatch({ 
      
      type:CREATE_PRODUCT, 
      productData: {
        id:resData.name,
        title , 
        imageUrl ,
        description ,
        price,
        mrp,        
        category
      }});
   
    }
 };

 export const updateProduct=(id, title , description,imageUrl , price ,mrp, category)=>{
   return async (dispatch)=>{
    

    const response=await fetch(`https://direp-marct.firebaseio.com/products/${id}.json`,{

   method:"PATCH",
   header:{
     "Content-type":"application.json"
   },
   body:JSON.stringify({
    title,
    description,
    imageUrl,
    price,
    mrp,
    category
  })

 })

    dispatch( { 
      
      type:UPDATE_PRODUCT, 
      pid:id ,
      productData:{ title,description, imageUrl , price,mrp ,category}}
   )
  }
  
};

     

这是我的减速器

import PRODUCTS from "../../data/dummy-data";
import {DELETE_PRODUCT , CREATE_PRODUCT , UPDATE_PRODUCT, SET_PRODUCTS , SOLD_PRODUCTS} from "../../store/actions/Product";
import Product from "../../models/Product";



const initialState={

    availableProduct : [],
    userProduct : []
 
    
 };

 export default (state=initialState , action) =>{
 
    switch (action.type){
        case SET_PRODUCTS:
          return{
            
            availableProduct:action.products,
            userProduct:action.products
          
          
          }
        case CREATE_PRODUCT:
            const newProduct = new Product(
              action.productData.id,
              'u1',
              action.productData.title,
              action.productData.imageUrl,
              action.productData.description,
              action.productData.price,
              action.productData.mrp,
              action.productData.category
            );
            return {
              ...state,
              availableProduct: state.availableProduct.concat(newProduct),
              userProduct: state.userProduct.concat(newProduct)
            };

          case UPDATE_PRODUCT:
            const productIndex = state.userProduct.findIndex(
              prod => prod.id === action.pid
            );
            const updatedProduct = new Product(
              action.pid,
              state.userProduct[productIndex].ownerId,
              action.productData.title,
              action.productData.imageUrl,
              action.productData.description,
              action.productData.price,
              action.productData.mrp,
              action.productData.category
            );
            const updatedUserProducts = [...state.userProduct];
            updatedUserProducts[productIndex] = updatedProduct;
            const availableProductIndex = state.availableProduct.findIndex(
              prod => prod.id === action.pid
            );


            const updatedAvailableProducts = [...state.availableProduct];
            updatedAvailableProducts[availableProductIndex] = updatedProduct;
            return {
              ...state,
              availableProduct: updatedAvailableProducts,
              userProduct: updatedUserProducts
            };

          case DELETE_PRODUCT:
            return {
              ...state,
              userProduct: state.userProduct.filter(
                product => product.id !== action.pid
              ),
              availableProduct: state.availableProduct.filter(
                product => product.id !== action.pid
              )
            };
        }
        return state;
      };
      

问题是,当我运行我的应用程序并单击特定类别(例如,Baby Care)时,首先没有获取任何产品,而我看到了一个空白屏幕。但是当我第二次单击我的产品时,我看到了结果。

我想要的是,当我单击类别而不是空白页面时,我希望最初看到提取的产品。 我认为问题出在UseEffect上,我不知道该怎么做,因为我是本机反应的新手。

在此先感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

问题在于这两部分以及它们如何协同工作:

      const UpdatedCategory=useSelector(state =>
        state.Products.availableProduct.filter((product)=>{
          return product.category == category
        } )
      );
      useEffect(()=>{   
        setCurrentCategory(UpdatedCategory)            
      },[])

UpdatedCategory来自useSelector钩子,这意味着状态更改时其值将更新。

但是此useEffect有一个空的依赖项数组[],这意味着setCurrentCategory仅在安装组件时被调用一次。

您希望CurrentCategory根据状态的变化保持更新,因此您需要在依赖项中加入UpdatedCategory

      useEffect(()=>{   
        setCurrentCategory(UpdatedCategory)            
      },[UpdatedCategory])