0

I am using Next and Tailwind/Daisy UI.

The code for the page below will fetch a JSON object from the API endpoint and render a top table of source systems and a lower table of domains attached. Clicking on a row in the top table filters the second table to the relevant domains. This all works fine. I also have a modal which is going to be used to create new source systems or edit existing ones. The [Edit] and [Create] buttons call the same function but the [Edit] button passes in the system ID and the [Create] button passes in -1 which is not a valid system id. The function call updates the SelectedSytemID store which is then used to filter the systems list for both the Domains table and the modal.

If when you load the page, you click on [Create] the modal opens and shows the placeholder (because the selectedSystemID is -1 and so not a valid system). If you click on an [Edit] button the modal opens and shows the system name (as it has found the correct system from the filter). If you now click on the [Create] button again, although the selectedSystemID is -1 and the filter function returns undefined, the modal input field is STILL showing the last filtered system name. I don't fully understand why and am looking for both an explanation of why the input value is not re-evaluated and how to fix it. I think I need either a useRef or useEffect but not sure where or how. Any help is much appreciated. I have replaced the API call with hard-coded JSON which is a cut down version of the response.

import { use, useEffect, useState } from "react";
import { listSourceSystems } from "./api/SourceSystems/index";

export default function Sourcesystem() {
  const [systems, setSystems] = useState([]);
  const [selectedSystemID, setSelectedSystemID]  = useState(-1)
  const [modalIsOpen, setModalisOpen] = useState(false)


  async function fetchData() {
     const listSourceSystems = [
      {
          "id": 1,
          "systemName": "Order Management",
          "domains": [
              {
                  "id": 1,
                  "domainName": "Customer"
              },
              {
                  "id": 2,
                  "domainName": "Order"
              },
          ]
      },
      {
          "id": 2,
          "systemName": "Warehouse Managment",
          "domains": [
              {
                  "id": 9,
                  "domainName": "Product"
              }
          ]
      }
  ]
   // setSystems(await listSourceSystems());
    setSystems(listSourceSystems)
    console.log(systems)
  }

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

  function filterDomains(systemID) {
    setSelectedSystemID(systemID)
  }

  function selectedSystem (){
    const ss = systems.filter(s=> s.id === selectedSystemID)[0]
    return ss
  }

  function openModal(systemID){
    filterDomains(systemID)
    setModalisOpen(true)
    console.log("openModal")
  }
  function closeModal(){
    setModalisOpen(false)
    console.log("closeModal")
  }

  return (
    <>
      <div className="flex flex-col mx-10 mt-4">
      <h1 className="text-3xl font-bold underline text-center">Source Systems</h1>
        <div className="divider"></div>
        <div className="grid h-50 card bg-base-300 rounded-box place-items-center">
          <table className="table table-compact w-full">
            <thead>
              <tr>
                <th className="font-bold px-5">Name</th>
                <th>actions</th>
              </tr>
            </thead>
            <tbody>
              {systems && systems.map((system) => (
                <tr 
                  key={system.id} 
                  className={`hover ${system.id === selectedSystemID? "active text-secondary font-bold": ""}`}
                  onClick={() => filterDomains(system.id)}
                >
                  <td className="px-5">{system.systemName}</td>
                  <td>
                    <button 
                      className="btn btn-primary btn-sm"
                      onClick={() => openModal(system.id)}
                    >
                      Edit
                    </button>
                  </td>
                </tr>
                ))}
            </tbody>
            <tfoot>
              <tr>
                <td colSpan="4" className="text-center font-bold accent">Add a new Source System</td>
                <td>
                  <button  
                    className="btn btn-primary btn-wide btn-sm"
                    onClick={()=> openModal(-1)}
                  >
                    click here
                  </button>
                </td>
              </tr>
            </tfoot>
          </table>
        </div>
        <div className="divider mt-0 before:bg-secondary after:bg-secondary"></div> 
        <div>
          <div className="grid h-20 card bg-primary-800 rounded-box place-items-center">
            <table className="table table-compact w-full table-fixed table-zebra">
              <thead>
                <tr>
                  <th className="text-left px-5">Domain</th>
                  <th className="text-right px-5">Source System</th>
                </tr>
              </thead>
              <tbody>
                { 
                  selectedSystem()?.domains.map(d => (
                    <tr key={d.id} className="hover">
                      <td className="px-5">{d.domainName}</td>
                      <td className="table-cell-2 text-right px-5">{systems.filter(s => s.id === selectedSystemID).systemName}</td>
                    </tr>
                  ))
                }
              </tbody>
            </table>
          </div>
        </div>
        {/* !-- Modal --> */}
        <input type="checkbox" id="source-system-modal" className=" modal-toggle" checked={modalIsOpen} />
        <div className="modal">
          <div className="modal-box">
            <h3>Source System Maintenance</h3>
            <form>
              <input 
                type="text" 
                placeholder="System Name placeholder"
                className="input input-bordered input-primary input-sm w-full"
                value={selectedSystem()?.systemName }
              >
              </input>
            </form>
            <div className="modal-action">
              <label htmlFor="source-system-modal" className="btn btn-info">Submit</label>
              <label htmlFor="source-system-modal" className="btn btn-warning btn-outline" onClick={()=> closeModal()}>Cancel</label>
            </div>
          </div>
        </div>
      </div>
    </>
  )}
Aaron Reese
  • 544
  • 6
  • 18

1 Answers1

0

Once again, as soon as I post it on Stack Overflow, it leads me down a different query path. Turns out the reason is pretty simple. The value in the input must always return a string so I need to do a ternary check and actually return an empty string if the function returns undefined

value={selectedSystem()? selectedSystem().systemName : "" }
Aaron Reese
  • 544
  • 6
  • 18