【问题标题】:too many renders react hooks, useEffect, map太多渲染反应钩子,useEffect,地图
【发布时间】:2021-04-16 03:53:33
【问题描述】:

大家好,我正在尝试为每次迭代添加一个简单的产品价格,并注意到它的运行次数过多。在使用效果上我得听听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>
    )

}

【问题讨论】:

    标签: firebase react-hooks use-effect


    【解决方案1】:
      useEffect(() => {
        if (user.currentUser) {
          setUserMail(user.currentUser.email);
          updateCart();
          updateStore();
        }
      }, [userCart]); //<-- userCart needs to be inside array
    

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

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

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

    【讨论】:

    • Ty 评论。在数组内部,它进入一个循环。
    • @YanivCode 我知道,我提到将变量作为useEffect 的第二个输入而不是数组传递是不正确的
    • 是一个不错的尝试添加另一个 useEffect 但它没有做的伎俩/:它只是不加载 userCart。没有可显示的错误
    • 在划分 useEffect 之后,它只运行 20 次渲染到 4 次。非常棒
    • @YanivCode 很高兴我能帮助兄弟 :),但接受答案我的意思是点击勾选按钮 (✔) ;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-19
    • 2020-04-23
    • 1970-01-01
    • 2021-01-06
    • 2020-06-27
    • 2020-08-16
    相关资源
    最近更新 更多