Home > Mobile >  Functions within the loop do not work with data from the database
Functions within the loop do not work with data from the database

Time:10-06

I have a problem and my code works fine when I fill the variable locally. However, as soon as I start a database call, the function inside the loop no longer works. The function ensures that cards can be opened or closed. (see the example)

How can I use the functions inside the loop with a database call?

Example: https://codepen.io/CreativeBulma/pen/YbQqoQ

This function also works in a loop if I store the data in a variable as follows const

[trainingData, setTrainingData] = useState([
    {
        ...
    },
    {
       ...
    }
]);

However, as soon as I make a database call and write the data in this way, nothing works anymore setTrainingData(res.data); That is, when I call the data with the function getTrainingData().

So as soon as I fill up const trainingData with a database, nothing works anymore.

Does not work

//database call
const [trainingData, setTrainingData] = useState([]);

    const getTrainingData = () => {
        axios
            .get(`${process.env.REACT_APP_API_URL}/team/team_training-${teamid}`,
        )
            .then((res) => {
                if (res.status === 200) {
                    if (typeof res.data !== 'undefined' && res.data.length > 0) {
                        // the array is defined and has at least one element
                        setIsTrainingExisting(true)
                        setTrainingData(res.data); // The data is the same as the working code
                        console.log(res.data)

                    }
                    else {
                        setIsTrainingExisting(false)
                    }


                }
            })
            .catch((error) => {
                //console.log(error);

            });

    }

// Console.log(res.data) give me the following output
/*
[
    {
        "von": "17:00",
        "bis": "18:00",
        "tag": "Mittwoch",
        "trainingsid": 46
    },
    {
        "von": "15:00",
        "bis": "19:00",
        "tag": "Donnerstag",
        "trainingsid": 47
    }
]
*/

Works

// without database call
const [trainingData, setTrainingData] = useState([
    {
        "von": "17:00",
        "bis": "18:00",
        "tag": "Mittwoch",
        "trainingsid": 46
    },
    {
        "von": "15:00",
        "bis": "19:00",
        "tag": "Donnerstag",
        "trainingsid": 47
    }
]);

Code

 import React, { useEffect, useRef, useState } from 'react'
import bulmaCollapsible from '@creativebulma/bulma-collapsible';
import axios from 'axios'

const teamid = (window.location.pathname).split("-")[1];

function Training() {

    let collapsiblesRef = useRef(null);


    useEffect(() => {
        bulmaCollapsible.attach(".is-collapsible", {
            container: collapsiblesRef.current
        });
    }, [])

    useEffect(() => {
        getTrainingData();
    }, []);

    const [isTrainingExisting, setIsTrainingExisting] = useState(false);
    const [trainingData, setTrainingData] = useState([]);
    

/*const [trainingData, setTrainingData] = useState([
    {
        "von": "17:00",
        "bis": "18:00",
        "tag": "Mittwoch",
        "trainingsid": 46
    },
    {
        "von": "15:00",
        "bis": "19:00",
        "tag": "Donnerstag",
        "trainingsid": 47
    }
]);*/

    const getTrainingData = () => {
        axios
            .get(`${process.env.REACT_APP_API_URL}/team/team_training-${teamid}`,
        )
            .then((res) => {
                if (res.status === 200) {
                    if (typeof res.data !== 'undefined' && res.data.length > 0) {
                        // the array is defined and has at least one element
                        setIsTrainingExisting(true)
                        setTrainingData(res.data);
                        console.log(res.data)

                    }
                    else {
                        setIsTrainingExisting(false)
                    }


                }
            })
            .catch((error) => {
                //console.log(error);

            });

    }





    return (
        <div>
            <div className="card">
                <div className="card-content">
                    <div ref={collapsiblesRef} id="accordion_first">

                        {trainingData.map((d, i) =>

                        (
                            <div className="card" key={i}>
                                <header className="card-header">
                                    <p className="card-header-title">
                                        {d.tag}
                                    </p>
                                    <a href={"#collapsible-message-accordion-"   i.toString()} data-action="collapse" className="card-header-icon is-hidden-fullscreen" aria-label="more options">
                                        <span className="icon">
                                            <i className="fas fa-angle-down" aria-hidden="true"></i>
                                        </span>
                                    </a>
                                </header>
                                <div id={"collapsible-message-accordion-"   i.toString()} className="is-collapsible" data-parent="accordion_first">
                                    <div className="card-content">
                                        <p className="is-small has-text-primary has-text-weight-semibold">Tag</p>

                                        <input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Wochentag" />
                                        <p className="is-small has-text-primary has-text-weight-semibold">Uhrzeit von</p>
                                        <input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Uhrzeit von" />

                                        <p className="is-small has-text-primary has-text-weight-semibold">Uhrzeit bis</p>
                                        <input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Uhrzeit bis" />

  

                                    </div>
                                </div>
                            </div>


                        ))}
                    </div>


                </div>
            </div>

            <br />

            <div>
                <button className="button is-light"> <i class="fas fa-plus-circle"></i>&nbsp; Neu</button>
            </div>


        </div>
    )
}

export default Training

CodePudding user response:

Why it's not working :

You're attaching the ref while the children are not rendered, so bulma does not know what to do to collapse your item when your components get the data from the api (since the call is async the component first render the data without the collapsible element).

What you can do to make it working :

  useEffect(() => {
        bulmaCollapsible.attach(".is-collapsible", {
            container: collapsiblesRef.current
        });
    }, [trainingData]) // <== will update bulma ref at every training data change
  • Related