Search code examples
reactjsreact-router-dom

innerHTML to Build Button which will use ReactJS navigate() when Button is Clicked Is Not Working


I am building a ReactJS app (React 18.2 and React-Router-Dom version 6.14.1) and using table.insertRow(row) and table.insertCell(column) to construct a multirow table with a Row ID link column that when clicked zooms in to the Details Page for that Row ID (primary key) as the image below shows.

enter image description here

When I use "a href" tag, the redirection works correctly in localhost environment and it zooms in to the master record for each row clicked. But it does not work when my ReactJS app is deployed in a JBOSS JWS server as a war file. I experimented with a few alternatives and found out that Navigate tag from react-router-dom works in JWS and also the Link tag.

WORKING IN LOCALHOST BUT NOT IN JWS (in JWS it is just staying on same page) -

myCell1.innerHTML = "<a href=" +  "ViewQuery?request_id=" + arr[2].trim() + "&id=" + id + "&name=" + username  + "&type=" + type + ">" + arr[2] + "</a>";

So I tried to implement the navigate(url_to_go_to) as per below image but I am getting error: "unable to find navigate or navigate is not defined. Invalid hook call. Hooks can only be called inside of the body of a function component."

I have already defined navigate in main function Main() (const navigate = useNavigate();) but I have commented it out and moved this line to function loadTableDataNotification(mov1) because that is where I am using the navigate keyword but it is giving me the error above.

NOT WORKING

myCell1.innerHTML = "<Button onClick= {navigate('/ViewQuery?function_id=" + arr[2].trim() + "&id=" + id + "&name=" + username  + "&type=" + type + "')}>" + arr[2] + "</Button>";

OR

myCell1.innerHTML = "<Link to= '/ViewQuery?function_id=" + arr[2].trim() + "&id=" + id + "&name=" + username  + "&type=" + type + "')}>" + arr[2] + "</Link>";

But I note that I cannot use React tags within innerHTML so how can I rewrite this portion.

Here is my code:

import * as ReactDOM from 'react-dom';
import React, { useEffect, useState } from "react";
import axios, {isCancel, AxiosError} from 'axios';
import { BrowserRouter, Routes, Route, Outlet, Link, NavLink, Navigate, useNavigate } from 'react-router-dom';
import AddNewQuery from "./AddNewQuery";
import ViewQuery from "./ViewQuery";

function Main() {


  //const navigate = useNavigate();


  const [items, setItems] = useState(null);

  
  const [result, setResult] = useState(null);

    
    
    function loadTableDataNotification(movray1) {

    const navigate = useNavigate();

      var table = document.getElementById("tableNotification");


      //REDRAW THE TABLE HEADER ROW        
      var row0 = table.insertRow();
      row0.style.fontSize = '12px'; row0.style.color = 'grey'; row0.style.fontWeight = 'bold';
      var myCell0 = row0.insertCell(counter0 + 0);
      myCell0.innerHTML = "Req ID";
      myCell0.innerHTML = "Description";

    movray1.forEach((movray) => {


      var me = " " + movray;
      var arr = me.split("|");


        var counter = 0;
        var row = table.insertRow();
        row.style.fontSize = "12px"; row.style.color = "grey";
        var myCell1 = row.insertCell(counter + 0);
        myCell1.innerHTML = "<Button onClick = {navigate('/ViewQuery?request_id=" + arr[0].trim() + "&id=" + id + "&name=" + username  + "&type=" + type + "')}>" + arr[0] + "</Button>";
        myCell1 = row.insertCell(counter + 1);
        myCell1.innerHTML = arr[1];


      });

    }
    



function Items({ currentItems }) {
  return (
    <div className="items"></div>
  );
}

  function PaginatedItemsNotification({itemsPerPage }) {


    const [currentItems, setCurrentItems] = useState(null);
    const [pageCount, setPageCount] = useState(0);
    const [itemOffset, setItemOffset] = useState(0);
  
  axios.get(window.globalURL + 'getEagleEyeRequestDataNotification/' + type + "/" + id)

  .then(function (response) {
   
    var myJson = JSON.parse(JSON.stringify(response.data));

  });


  var items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
 
  
  useEffect(() => {

  axios.get(urlString)    

  .then(function (response) {

        var myJson = JSON.parse(JSON.stringify(response.data));

        var my_items_array = new Array();
   

      for (let i = 0; i < response.data.length; i++) {
        my_items_array.push(response.data[i].request_id
        + "|" + response.data[i].description);
    }

        
        const endOffset = itemOffset + itemsPerPage;
        setCurrentItems(my_items_array.slice(itemOffset, endOffset));
        setPageCount(Math.ceil(items.length / itemsPerPage));

        
        loadTableDataNotification(my_items_array.slice(itemOffset, endOffset));
        
      });


      }, [itemOffset, itemsPerPage]);



      const handlePageClick = (event) => {
        const newOffset = event.selected * itemsPerPage % items.length;
        console.log(`User requested page number ${event.selected}, which is offset ${newOffset}`);
        setItemOffset(newOffset);
      };

      
      return (
        <>
          <Items currentItems={currentItems} />
          <ReactPaginate
            nextLabel="next >"
            onPageChange={handlePageClick}
            pageRangeDisplayed={3}
            marginPagesDisplayed={2}
            pageCount={pageCount}
            previousLabel="< previous"
            pageClassName="page-item"
            pageLinkClassName="page-link"
            previousClassName="page-item"
            previousLinkClassName="page-link"
            nextClassName="page-item"
            nextLinkClassName="page-link"
            breakLabel="..."
            breakClassName="page-item"
            breakLinkClassName="page-link"
            containerClassName="pagination"
            activeClassName="active"
            renderOnZeroPageCount={null}
          />
        </>
      );



}


  return (


    <div id = 'myApp' style={{margin: "10px"}}>

      <Routes>
          <Route path="ViewQuery" element={<ViewQuery />} />
      </Routes>



     <table style={{padding:0}}><tr><td style={{backgroundColor:"#b6e4fe", color:"white", width:"8%"}}></td><td>


      <br/>

      <table style={{ width: '100%', borderTop: '1px solid grey', borderBottom: '1px solid grey', textAlign: 'left', fontFamily: 'Calibri', fontSize: '18px', color: 'grey', fontWeight: 'bold' }}><tr><td>NOTIFICATION</td></tr></table>
 

      <table id="tableNotification" cellspacing="5" cellpadding="5">
        <thead>
        <tr style={tableHeaderRow}>
            <td>Req ID</td>
            <td>Description</td>         
          </tr>
        </thead>
        <tbody id="tableNotificationBody"></tbody>  
      </table>


    </div>
     
    );


}

export default Main;

Solution

  • I guess because you define function in string it does not work correctly so

      const btn = document.createElement("button");
    
      btn.onclick = ()=> navigate('/ViewQuery?request_id=' + arr[0].trim() + '&id=' + id + 
      '&name=' + username  + '&type=' + type);
       
       myCell1.appendChild(btn);
    

    maybe it works and for prevent re render You can use useEffect or clearing children of myCell1 on re render