太多渲染反应钩子,useEffect,地图

时间:2021-01-11 07:35:14

标签: firebase react-hooks use-effect

嘿伙计们,我正在尝试为每次迭代添加一个简单的产品价格,并注意到它的运行次数太多了。在使用效果上我得听听UserCart。不能用空数组/[userCart] 做到这一点。 我还在更多组件中遇到以下错误,由于与 useEffect 中的最后一个参数相同的原因,我无法修复这些错误:

更新:我确实按照建议划分了 useEffect 但它与 [userCart ] 进入了无限循环

代码:

  import React, { useState, useEffect } from 'react'
    import firebase from 'firebase';
    import { useAuth, useStoreUpdate } from '../contexts/FirebaseContext';
    
        export default function Cart() {
            const [userMail, setUserMail] = useState(undefined)
            const [userCart, setUserCart] = useState(undefined)
            const [totalAmmout, setTotalAmmout] = useState(0)
            const user = useAuth()
            const userDoc = firebase.firestore().collection("cart").doc(userMail)
            const updateStore = useStoreUpdate()
        
            const updateCart = () => {
                userDoc.get().then((doc) => {
                    if (doc.exists) {
                        let cart = doc.data()
                        setUserCart(cart)
                    }
                })
            }
        
            async function removeFromCart(itemId, name, url, price, category, type, description) {
                const cartItem = { itemId, name, url, price, category, type, description }
                await userDoc.update({
                    item: firebase.firestore.FieldValue.arrayRemove(cartItem)
                })
                await updateCart()
                await updateStore()
            }
        
            useEffect(() => {
                if (user.currentUser) {
                    setUserMail(user.currentUser.email)
                    updateCart()
                    updateStore()
        
                }
            },userCart)
        
            if (!userCart) return <h1>hold</h1>
            let total = 0
            return (
                <main className="main-cart">
                    <div className="container">
                        {userCart.item && userCart.item.length >= 1 && userCart.item.map((item, i, arr) => {
                           
                            console.log(item);  //it runs more than 20 times
                            return (
                                < div className="item-container" key={item.itemId} >
                                    <h3>{item.name}</h3>
                                    <p>{item.price}</p>
                                    <img height="150px" width="150px" src={item.url} alt="" />
                                    <button onClick={async () => {
                                        await removeFromCart(item.itemId, item.name, item.url, item.price, item.category, item.type, item.description)
                                    }}>X</button>
                                </div>
                            )
                        })}
        
                    </div>
                    <div className="fixed-bottom-link">
                        <button>finish purchase</button>
                    </div>
                </main >
            )
        }

编辑:

我找到了主要组件,但仍然无法使其工作 第二个 useEffect [userCart] 不会运行,它只在不在数组中时才起作用,但它进入循环:

import React, { useContext, useState, useEffect } from 'react';
import { auth } from '../firebase/firebase';
import firebase from '../firebase/firebase';

const FirebaseContext = React.createContext()
const StoreContext = React.createContext()
const StoreContextUpdate = React.createContext()

export function useAuth() {
    return useContext(FirebaseContext)
}
export function useStore() {
    return useContext(StoreContext)
}

export function useStoreUpdate() {
    return useContext(StoreContextUpdate)
}

export function AuthProvider({ children }) {
    const [currentUser, setCurrentUser] = useState();
    const [loading, setLoading] = useState(true)
    const [userMail, setUserMail] = useState(undefined)
    const [userCart, setUserCart] = useState(undefined)
    const userDoc = firebase.firestore().collection("cart").doc(userMail)

    const updateCart = () => {
        userDoc.get().then((doc) => {
            if (doc.exists) {
                let cart = doc.data()
                setUserCart(cart)
            }
        })
    }


    function signup(email, password) {
        return auth.createUserWithEmailAndPassword(email, password)
    }

    function login(email, pasword) {
        return auth.signInWithEmailAndPassword(email, pasword)
    }

    function logout() {
        return auth.signOut()
    }
    useEffect(() => {
        const unsubscribe = auth.onAuthStateChanged(async user => {
            await setCurrentUser(user)
            
            await setLoading(false)
        })
        return unsubscribe
    }, [userCart])

    useEffect(()=>{
        async function refreshCart(){
             await setUserMail(currentUser.email);
             await updateCart()   
         }
        if (currentUser && currentUser.email) {
               refreshCart()
           
        }
        return
    },[userCart])



    const value = {
        currentUser,
        signup,
        login,
        logout
    }
    return (
        <FirebaseContext.Provider value={value}>
            <StoreContext.Provider value={userCart && userCart.item}>
                <StoreContextUpdate.Provider value={updateCart}>
                    {!loading && children}
                </StoreContextUpdate.Provider>
            </StoreContext.Provider>
        </FirebaseContext.Provider>
    )

}

1 个答案:

答案 0 :(得分:1)

  useEffect(() => {
    if (user.currentUser) {
      setUserMail(user.currentUser.email);
      updateCart();
      updateStore();
    }
  }, [userCart]); //<-- userCart needs to be inside array

重新渲染过多的原因是您在 updateCart 更改时调用 userCart 函数,然后 userCart 更改将导致再次调用 updateCart 并且这循环会一直重复直到内存不足

我认为添加另一个 useEffect 可能对您有所帮助

  useEffect(() => {
    if (user.currentUser) {
      setUserMail(user.currentUser.email);
      updateStore();
    }
  }, [userCart]); //<-- userCart needs to be inside array

  useEffect(() => {
    if (user.currentUser) {
      updateCart();
    }
  }, []);