How to update values of useRef variables in a useEffect

Viewed 711

I am building a webpage in a bug tracker project where a user can view certain types of tickets in a graph after logging in. I'm retrieving these tickets by making an api call in the function getTickets(), and setting them as state. I have useEffect that contains a function which maps through the tickets, & saves the count of the amount of tickets per type in useRef vars. These vars are then getting set in data() which sets the data for the graph.

How would I go about updating these useRefs? When I log these useRefs they are all null. Also, since setChartData() is asynchronous, would I have to create another useEffect with a dependency that only calls data() when these useRefs get updated?

getTickets()

const getTickets = () => {
            fetch("/api/Ticket")
                .then((response) => response.json())
                .then((data) => {
                    console.log(data)
                    setTickets(data)
                })
                .catch((error) => {
                    console.log(error)
                });
        }

mapTickets()

const mapTickets = () => {
    tickets.map((ticket) => (
        ticket.status == "None" ?
            noneTickets.current.tickets += 1
            : (
                noneTickets.current.tickets = 0
            ),
        ticket.status == "Low" ?
            lowTickets.current.tickets += 1
            : (
                lowTickets.current.tickets = 0
            ),
        ticket.status == "Medium" ?
            mediumTickets.current.tickets += 1
            : (
                mediumTickets.current.tickets = 0
            ),
        ticket.status == "High" ?
            highTickets.current.tickets += 1
            : (
                highTickets.current.tickets = 0
            )
    ))

    
}

data()

const data = () => {
            setChartData({
                labels: ['None', 'Low', 'Medium', 'High'],
                datasets: [
                    {
                        label: 'ticket priority',
                        data: [noneTickets.current.tickets, lowTickets.current.tickets, mediumTickets.current.tickets, highTickets.current.tick],
                        backgroundColor: [
                            'rgba(75, 192, 192, 0.6)'
                        ],
                        borderWidth: 4
                    }
                ]
            })
        }

useEffect (only updates useRefs & sets chart data if tickets are updated)

useEffect(() => {
    mapTickets();
    data();
}, [tickets])

useEffect (sets tickets in state)

useEffect(() => {
    getTickets();
    const requestOptions = {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
            ApplicationUserusername: location.state.username,
        }),
    };
    fetch("/api/IssueTracker/dashboard", requestOptions)
        .then((response) => response.json())
        .then((data) => {
            setProjects(data);
        })
        .catch((error) => {
            console.log(error)
        });
    
           
}, [])
1 Answers
  1. Changes needs to be re-render
  2. In foreach don't change other values to 0

function App() {
  const [tickets, setTickets] = React.useState([]);
  const [notifyChange, setNotifyChange] = React.useState(false);
  const noneTickets = React.useRef({ tickets: 0 });
  const lowTickets = React.useRef({ tickets: 0 });
  const mediumTickets = React.useRef({ tickets: 0 });
  const highTickets = React.useRef({ tickets: 0 });

  React.useEffect(() => {
    setTickets([
      { status: "None" },
      { status: "None" },
      { status: "Low" },
      { status: "None" },
      { status: "Low" },
      { status: "Medium" },
      { status: "None" },
      { status: "Medium" },
      { status: "Medium" },
      { status: "High" },
      { status: "High" },
      { status: "High" },
      { status: "High" },
    ]);
  }, []);

  const mapTickets = () => {
    tickets.forEach((ticket) => {
      switch (ticket.status) {
        case "None":
          noneTickets.current.tickets += 1;
          break;
        case "Low":
          lowTickets.current.tickets += 1;
          break;
        case "Medium":
          mediumTickets.current.tickets += 1;
          break;
        case "High":
          highTickets.current.tickets += 1;
          break;
      }
    });
    // Here is the trick to re render the changes 
    setNotifyChange(!notifyChange)
  };
  
  React.useEffect(() => {
    mapTickets();
  }, [tickets]);
  
  return (
    <ul>
      <li>None: {noneTickets.current.tickets}</li>
      <li>Low: {lowTickets.current.tickets}</li>
      <li>Medium: {mediumTickets.current.tickets}</li>
      <li>High: {highTickets.current.tickets}</li>
    </ul>
  );
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Related