Jon Nicholson
Jon Nicholson

Reputation: 1131

Attempting to map through an array of data and push items to different arrays

I'm building a function at the moment which receives data from an API call, maps through it (it's an array of objects), and pushes an item to a respective array depending on one of its values.

However, it only seems to be pushing one item into each array and no more.

There are no errors in my code, so not sure what I'm doing wrong - I assume I'm overwriting the array each time but not sure.

Here's the state arrays which the items need to be pushed into:

const [backlog, setBacklog] = useState([])
const [inProgress, setInProgress] = useState([])
const [paused, setPaused] = useState([])
const [completed, setCompleted] = useState([])

And here is the function itself:

const fetchData = async () => {
    await axios.get("/api/fetch/fetchData")
        .then(async (response) => {

            const data = await response.data;

            setAllTasks(data)

            data.map(item => {

                if (item.status === 'backlog') {
                    setBacklog([...backlog, item])
                } else if (item.status === 'in-progress') {
                    console.log(item)
                    setInProgress([...inProgress, item])
                } else if (item.status === 'paused') {
                    setPaused([...paused, item])
                } else if (item.status === 'completed') {
                    setCompleted([...completed, item])
                }
                
            })
        })
    }

Upvotes: 0

Views: 484

Answers (2)

akabin
akabin

Reputation: 103

I think your axios call is considerably more complicated than it needs to be. All those extra async/await & then calls may be your issue. Here's a much simpler solution:

const fetchData = async () => {
    const response = await axios.get("/api/fetch/fetchData");
    const data = response.data;

    data.map(item => {

                if (item.status === 'backlog') {
                    setBacklog(prevBackLog => [...prevBackLog, item])
                } else if (item.status === 'in-progress') {
                    console.log(item)
                    setInProgress(prevInProgress => [...prevInProgress, item])
                } else if (item.status === 'paused') {
                    setPaused(prevPaused => [...prevPaused, item])
                } else if (item.status === 'completed') {
                    setCompleted(prevSetCompleted => [...prevSetCompleted, item])
                }

            })
}

Upvotes: 1

Henry Ecker
Henry Ecker

Reputation: 35636

Because set functions are batched it's likely that the variable has not yet been updated.

To modify your program (as is) use function state updating:

const fetchData = async () => {
    await axios.get("/api/fetch/fetchData")
        .then(async (response) => {

            const data = await response.data;

            setAllTasks(data)

            data.map(item => {

                if (item.status === 'backlog') {
                    setBacklog(prevBackLog => [...prevBackLog, item])
                } else if (item.status === 'in-progress') {
                    console.log(item)
                    setInProgress(prevInProgress => [...prevInProgress, item])
                } else if (item.status === 'paused') {
                    setPaused(prevPaused => [...prevPaused, item])
                } else if (item.status === 'completed') {
                    setCompleted(prevSetCompleted => [...prevSetCompleted, item])
                }

            })
        })
}

Note: it would be much better to come up with a way to use a single set function to update all of these values in one state update.

Maybe with the currently available set functions building a complete state and doing one update per status doing something like:

function groupBy(arr, property) {
    return arr.reduce(function (memo, x) {
        if (!memo[x[property]]) {
            memo[x[property]] = [];
        }
        memo[x[property]].push(x);
        return memo;
    }, {});
}

data = groupBy(data, 'status')

setBacklog(prevBackLog => [...prevBackLog, ...data['backlog']])
setInProgress(prevInProgress => [...prevInProgress, ...data['in-progress']])
setPaused(prevPaused => [...prevPaused, ...data['paused']])
setCompleted(prevSetCompleted => [...prevSetCompleted, ...data['completed']])

Upvotes: 1

Related Questions