简体   繁体   中英

useEffect Object dependency infinite loop - ReactJS

I have a State in Context with Object. I am running a async function in the useEffect and passing my object state as dependency .

I passed the state object as dependency because i want to re-render the component when values of settings object changes.

But it causes an infinite loop.

Update:
Let me clear my question more.
In my useEffect , I am calling my async function addTextItem() which calls the function finalPrice and it updates the state, but this way it causes infinite loop.
On other hand, If i call finalPrice in the useEffect directly instead of calling addTextItem then there is no infinite loop but it is also updating the state, right? then how this could be. & I need a solution as i have tried everything and now totally stuck.

Here is the code:

export default function CustomizerState(props) {
    const initialText = "Hello"
    const initialSize = {
        x: REACT_APP_SIZE_X,
        y: REACT_APP_SIZE_Y
    }
    const initialTextItem = {
        id: generateID(),
        text: "Hello",
        font: fonts[0].value,
        size: initialSize,
        color: colors[0],
        backplate: "cut-sharp",
        uvPrint: false,
        quantity: 1,
        neonPrice: 0,
        backplatePrice: 0,
        neonPower: 0,
        totalPrice: 0
    }
    const [settings, setSettings] = useState({
        textItems: [],
        libraryItems: [],
        ownDesigns: [],
        accessories: [
            // My Objects here
        ],
        finalPrice: 0
    })

    const addTextItem = async () => {
        const pathLength = await textToPath(initialText, initialSize.x)
        const { backplatePrice, neonPrice, neonPower, totalPrice } = calculateSvgPrice(pathLength)
        const id = generateID()

        const newItems = [
            ...settings.textItems,
            {...initialTextItem, id, backplatePrice, neonPrice, neonPower, totalPrice}
        ]
        
        finalPrice("textItems", newItems)
    }

    const finalPrice = (itemType = null, items = null) => {
        const textItemsPrice = getTotalPrice()
        const libraryItemsPrice = getTotalPrice("libraryItems")
        const accessoriesPrice = getTotalPrice("accessories", "unitPrice")

        const finalPrice = textItemsPrice + libraryItemsPrice + parseInt(accessoriesPrice)

        if (itemType === null) {
            setSettings((prevState) => (
                {...prevState, finalPrice}
            ))
            return false
        }

        setSettings((prevState) => (
            {...prevState, [itemType]: items, finalPrice}
        ))
    }

    useEffect(() => {
        // It will add first initial form item
        addTextItem()
    }, [JSON.stringify(settings)])

    return (
        <CustomizerContext.Provider value={{settings, addTextItem}}>
            {props.children}
        </CustomizerContext.Provider>
    )
}

在此处输入图像描述

I have google and tried the solutions, but nothing worked for me. Can someone help me to fix this issue? I am stuck....

Check the useEffect hook documentation . The array passed in the second argument array is the dependency array:

useEffect(() => {
    //hook code   
}, []);

The dependency array will make the hook code execute everytime any variable of the array changes. In your case you are changing the depency item settings in the call itself producing an infinite loop.

I forgot that when re-rendering happens, it also runs useEffect obviously and it causes setState again and again.
I managed to fix this by creating a state named initialItemCount with 0 initial value. I am checking if that state value is 0 then run addTextItem which will add my initial form item and updates the final price, but if the value 1 then only run the finalPrice function.

const [initialItemCount, setInitialItemCount] = useState(0)
useEffect(() => {
    if (initialItemCount === 0) {
        addTextItem()
        setInitialItemCount(1)
    }
    
    if (initialItemCount === 1) {
        finalPrice()
    }
}, [JSON.stringify(settings)])

Finally, inner peace.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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