Why does optional chaining allows rendering when fetching data through useEffect in an app that uses context?

I’m new to the webdev world and want to learn ReactJS. I followed a tutorial I found on YouTube made by Traversy where he makes a task tracker and now I want to make some changes to it to learn and practice some more.

I want to use context for the appointments (originally named tasks in the tutorial), add a calendar with react-calendar and use react-router-dom.
I got stuck for a while trying to make the list render, because it only rendered “empty”. Later on found this post with a similar issue to mine: Only run a useEffect fetch after first useEffect fetch has fired and setUser in context

I changed bits of my code based on that post and now it does render the appointment list, but I don’t know why it didn’t work before and I’m unsure on why it does work now. I don’t even know if I’m using context correctly or just prop-drilling. Help would be greatly appreciated. Thank you.

Also, sorry if my code is a mess, I’m new at this.

App.js

import { createContext, useState, useEffect } from "react";
import Dashboard from "./views/Dashboard";
import './App.css';
import { BrowserRouter as Router, Route, Routes} from "react-router-dom";
import AddAppointmentForm from "./views/AddAppointmentForm";

export const AppContext = createContext();
export const AppUpdateContext = createContext();

function App() {
  const [appointments, setAppointments] = useState([])
  const updateAppointments = (apptList) => {
    setAppointments(apptList)
  }

  return (
    <AppContext.Provider value={ appointments }>
      <AppUpdateContext.Provider value={ updateAppointments }>
        <Router>
          <Routes>
            
              <Route path="/" element={<Dashboard appointments={appointments} />} />
              {/* <Route path="/add" element={<AddAppointmentForm />} />  TBA */} 
            
          </Routes>
        </Router>
      </AppUpdateContext.Provider>
    </AppContext.Provider>
  );
}

export default App;

Dashboard.js

import { useEffect, useContext} from "react";
import { AppContext } from "../App";
import { AppUpdateContext } from "../App";
import AppointmentList from "../components/AppointmentList";
import Header from "../components/Header";

// function Dashboard() {  // this is how it used to be
  function Dashboard(props) {
  const appointments = useContext(AppContext)
  const setAppointments = useContext(AppUpdateContext)

  const fetchAppointmentList = async () => {
    const res = await fetch("http://localhost:5000/appointments");
    const data = await res.json();

    return data;
  }

  useEffect(() => {
    const getAppointments = async () => {
      const appointmentsFromServer = await fetchAppointmentList();
      setAppointments(appointmentsFromServer);
    }

    getAppointments();
    console.log("ñññññ",appointments)
  }, []);
  
  console.log("aagh",appointments)
  
  return (
    <div style={dashboardStyle}>
      <Header />
      {/* {appointments.lenght>0 ? (<AppointmentList />) : <p>empty</p>} this is how it used to be */}
      <AppointmentList appointments={props?.appointments}/>
    </div>
  );
}

const dashboardStyle = {
  maxWidth: "31.25rem",
  overflow: "auto",
  minHeight: "18.75rem",
  border: "1px solid steelblue",
  margin: "1.875rem auto",
  padding: ".5rem",
  boxSizing: "border-box",
}

export default Dashboard;

AppointmentList.js

import Appointment from "./Appointment";
import { AppContext } from "../App";
import { useContext } from "react";

function AppointmentList({ appointments }) {
// function AppointmentList() {  // this is how it used to be
  // const { appointments, setAppointments } = useContext(AppContext)
  console.log("appList",appointments)  // this is how it used to be

  return (
    <>
      {
        appointments.map(appt => (
          <Appointment key={appt.id} appointment={appt} />
        ))
      }
    </>
  );
}

export default AppointmentList;