0

I am looping through the contents of the following array:

chosenBets: [
    {
        id: 2,
        label: 2,
        odd: 4.8,
        team_home: "Liverpool",
        team_away: "Sheffield United",
    },
    {
        id: 2,
        label: 2,
        odd: 4.8,
        team_home: "Liverpool",
        team_away: "Sheffield United",
    },
],

To get the total odds of each bet:

const getTotalOdds = () => {
    let totalOdds = 0
    chosenBets.forEach(bet => {
        totalOdds += bet.odd
    })

    let newState = Object.assign({}, state)
    newState.totalOdds = totalOdds
    setState({ ...newState })
}

But when I call the function inside of useEffect it causes an infinite loop.

Full code:

import * as React from "react"
import { Frame, Stack, addPropertyControls, ControlType } from "framer"
import { Input } from "./Input"

interface Bets {
    id: number
    label: number
    odd: number
    team_home: string
    team_away: string
}

interface IProps {
    chosenBets: Bets[]
}

const style = {
    span: {
        display: "block",
    },
}

const Row = ({ label, property }) => (
    <div style={{ display: "flex", width: "100%" }}>
        <span style={{ ...style.span, marginRight: "auto" }}>{label}</span>
        <span style={{ ...style.span }}>{property}</span>
    </div>
)

export const BetCalculator: React.FC<IProps> = props => {
    const { chosenBets } = props

    const [state, setState] = React.useState({
        stake: 10,
        totalOdds: 0,
        potentialPayout: 0,
    })

    const { stake, totalOdds } = state

    const onChange = e => {
        let newState = Object.assign({}, state)
        newState.stake = Number(e.value)
        setState({ ...newState })
    }

    const getTotalOdds = () => {
        let totalOdds = 0
        chosenBets.forEach(bet => {
            totalOdds += bet.odd
        })

        let newState = Object.assign({}, state)
        newState.totalOdds = totalOdds
        setState({ ...newState })
    }

    const getPayout = () => {
        let potentialPayout = totalOdds * stake
        console.log(potentialPayout, "potentialPayout")
        // let newState = Object.assign({}, state)
        // newState.potentialPayout = potentialPayout
        // setState({ ...newState })
    }

    React.useEffect(() => {
        getTotalOdds()
        getPayout()
    }, [state])

    return (
        <Stack alignment="end" backgroundColor="white">
            <Row
                label="stake"
                property={<Input onChange={onChange} value={stake} />}
            />
            <Row label="Odds" property={totalOdds} />
        </Stack>
    )
}

BetCalculator.defaultProps = {
    chosenBets: [
        {
            id: 2,
            label: 2,
            odd: 4.8,
            team_home: "Liverpool",
            team_away: "Sheffield United",
        },
        {
            id: 2,
            label: 2,
            odd: 4.8,
            team_home: "Liverpool",
            team_away: "Sheffield United",
        },
    ],
}

My questions are as follows:

  • What is causing this?
  • How do I resolve?
1
  • 1
    When you call getPayout or getTotalOdds you update the state and the effect is run when the state changes which then calls those methods which update the state but the effect runs when you update the state and it calls those methods which update the state... is the reason for the infinite loop. Commented Oct 2, 2019 at 11:06

1 Answer 1

3
  1. You can divide state into smaller chunks:
const [stake, setStake] = useState(10);
const [totalOdds, setTotalOdds] = useState(0);
const [potentialPayout, setPotentialPayout] = useState(0);

Easier to manage.

  1. If your useEffect is called every time state has changed, and on the other hand every useEffect returns new state object - well. Infinite loop.

Just put the calculations in the onChange function and you won't need useEffect at all (or just use useEffect to cause side effects, like console.log);

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.