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....
CodePudding user response:
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.
CodePudding user response:
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.