Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Link tag changes the url but doesnt render the component

I'm trying to build an app with react frontend, I have a navbar with a search box and when I click the result from search I want to redirect to a specific url for which I use a Link tag wrappped around the result component, but when I click the result component, the url changes but the component is not re rendered. I'm unable to Route only when im using Link inside my navbar, in other components link works as intended. This is my App.js

import {BrowserRouter as Router, Routes, Route} from 'react-router-dom'
import Entity from './components/Entity';
import Navbar from './components/Navbar';
import Video from './components/Video';
import AddEntity from './components/AddEntity';
import AddEpisode from './components/AddEpisode';

function App() {
  return (
    <Router>
        <div className="App bg-gradient-to-r from-slate-900 to-slate-700 h-full w-full">
          <Navbar />
          <Routes>
            <Route exact path="/entity/:id" element={<Entity />} />
              <Route exact path="/admin/entity/add" element={<AddEntity />} />
              <Route exact path="/admin/entity/:id/addEpisode" element={<AddEpisode />}/>
              <Route exact path="/entity/:id/:episode" element={<Video />} />
          </Routes>
        </div>
    </Router>
  );
}

export default App;

This is my Navbar.js

import axios from "axios"
import { Link, useNavigate } from "react-router-dom"
import { useEffect, useState } from "react/cjs/react.development"
import config from './../config'          
                                                                                              
const Navbar = () => {
  const navigate = useNavigate()
  const [text,setText] = useState("")  
  const onInputChange = (ev) => {
    setText(ev.target.value)
  }
  const [searchResults, setSearchResults] = useState([])
  const [resComps, setResComps] = useState([])
  useEffect(() => {
    if(text == ""){
      return
    }
    const data = {
      "search_text": text
    }
    axios.post(`${config.EntityServer}/entity/search`,data).then((res) => {
      let daxa = res.data.data
      if(daxa.hits.hits){
        const neededArr = daxa.hits.hits.map((hit) => {
          return{
            id: hit._id,
            cover_url: hit._source.cover_url,
            english: hit._source.english,
            japanese: hit._source.japanese,
            views: hit._source.views,
            mongo_id: hit._source.mongo_id
          }
        })
        console.log(neededArr)
        setSearchResults(neededArr)
      }
    })
  },[text, setSearchResults])

  const onDivClick = (ev) => {
    let ele = ev.target
    while(ele.getAttribute('id') === null) {
      ele = ele.parentNode
    }
    const id = ele.getAttribute('id')
    let current = window.location.href.split("/")
    console.log(current)
    const url = current[0] + '//' + current[2] + `/entity/${id}`
    window.location.assign(url)
  }

  useEffect(() => {
    if(!searchResults){
      return
    }
    const arr = searchResults.map(s => {
      return(
        <Link to={`/entity/${s.mongo_id}`}>
        <div className="flex flex-row mt-3 hover:bg-gray-700 hover:cursor-pointer" key={s.mongo_id} id={s.mongo_id}>
          <div className="flex-1 w-full h-5/6">
            <img className="object-cover border-2 border-cyan-500" src={`${config.ImageServer}/image/${s.cover_url}`} alt={s.mongo_id} />
          </div>
          <div className="flex-2 w-5/6 h-full">
            <p className="text-xl text-violet-500 ml-2">{s.english}</p>
            <p className="text-md text-violet-500 ml-2">{s.japanese}</p>
          </div>
        </div>
        </Link>
      )
    })
    setResComps(arr)
  },[searchResults, setResComps])

return (
<div className="w-full">
<nav className="bg-white border-gray-200 px-2 sm:px-4 py-2.5 rounded dark:bg-gray-800 fixed top-0 left-0 w-full max-h-15">
  <div className="container flex flex-wrap justify-between items-center mx-auto">
  <a href="#" className="flex">
    <svg className="mr-3 h-10" viewBox="0 0 52 72" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1.87695 53H28.7791C41.5357 53 51.877 42.7025 51.877 30H24.9748C12.2182 30 1.87695 40.2975 1.87695 53Z" fill="#76A9FA"/><path d="M0.000409561 32.1646L0.000409561 66.4111C12.8618 66.4111 23.2881 55.9849 23.2881 43.1235L23.2881 8.87689C10.9966 8.98066 1.39567 19.5573 0.000409561 32.1646Z" fill="#A4CAFE"/><path d="M50.877 5H23.9748C11.2182 5 0.876953 15.2975 0.876953 28H27.7791C40.5357 28 50.877 17.7025 50.877 5Z" fill="#1C64F2"/></svg>
      <span className="self-center text-lg font-semibold whitespace-nowrap dark:text-white">FlowBite</span>
  </a>
  <div className="flex md:order-2">
  <div className="flex justify-center mr-12">
  <div className="xl:w-80">
    <div className="input-group relative flex flex-wrap items-stretch w-full">
      <input type="search" className="form-control relative flex-auto min-w-0 block w-3/6 px-3 py-1.5 text-base font-normal text-violet-500 bg-gray-700 bg-clip-padding border border-solid border-gray-300 rounded transition ease-in-out m-0 focus:border-cyan-500 focus:outline-none" value={text} onChange={onInputChange} placeholder="Search" aria-label="Search" aria-describedby="button-addon2" />
    </div>
  </div>
</div>
      <button type="button" className="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center mr-3 md:mr-0 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">Get Started</button>
      <button data-collapse-toggle="mobile-menu-4" type="button" className="inline-flex items-center p-2 text-sm text-gray-500 rounded-lg md:hidden hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:hover:bg-gray-700 dark:focus:ring-gray-600" aria-controls="mobile-menu-4" aria-expanded="false">
      <span className="sr-only">Open main menu</span>
      <svg className="w-6 h-6" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fillRule="evenodd" d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 15a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1z" clipRule="evenodd"></path></svg>
      <svg className="hidden w-6 h-6" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fillRule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clipRule="evenodd"></path></svg>
    </button>
  </div>
  <div className="hidden justify-between items-center w-full md:flex md:w-auto md:order-1" id="mobile-menu-4">
    <ul className="flex flex-col mt-4 md:flex-row md:space-x-8 md:mt-0 md:text-sm md:font-medium">
      <li>
        <a href="#" className="block py-2 pr-4 pl-3 mr-8 text-white bg-blue-700 rounded md:bg-transparent md:text-blue-700 md:p-0 dark:text-white" aria-current="page">Home</a>
      </li>
      <li>
        <a href="#" className="block py-2 pr-4 pl-3 mr-8 text-gray-700 border-b border-gray-100 hover:bg-gray-50 md:hover:bg-transparent md:border-0 md:hover:text-blue-700 md:p-0 md:dark:hover:text-white dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent dark:border-gray-700">About</a>
      </li>
    </ul>
  </div>
  </div>
</nav>
<div className="fixed right-[18%] top-14 bg-gray-800 w-80">
  <ul>
  <li>{(resComps && resComps.length > 0)? <div className="max-h-60 overflow-y-scroll scrollbar-hide border-2 border-t-0 border-gray-900">{resComps}</div>: <div></div>}</li>
  </ul>
</div>
</div>
)
}

useNavigate doesnt work too.. This is Entity.js where usenavigate works..

import axios from "axios"
import { useEffect, useRef, useState } from "react"
import { useNavigate, useParams } from "react-router-dom"
import config from "../config"
const Entity = () => {
    const {id} = useParams()
    const navigate = useNavigate()
    const [entity, setEntity] = useState({})
    const [comps, setComps] = useState([])
    const firstUpdate = useRef(true)
    const onButtonClick = (ev) => {
        const target = ev.target
        navigate(target.getAttribute('url'))
    }
    
    useEffect(() => {
        axios.get(`${config.EntityServer}/entity/${id}`).then((d) => {
            const data = d.data
            if(data.result){
                setEntity(data.data)
            }
        }).catch(err => {
            console.log(err)
        })
    },[])

    useEffect(() => {
        if(firstUpdate.current) {
            firstUpdate.current = false
            return
        }
        const cps = entity.episodes.map((epi, index) => {
            return(
                <button className="rounded-full w-28 h-10 shadow-lg shadow-cyan-500/50 bg-cyan-500 text-white font-bold text-lg hover:shadow-cyan-500/90" url={`/entity/${entity.id}/${index+1}`} key={index} onClick={onButtonClick}>
                    {epi.title}
                </button>
            )
        })
        setComps(cps)
    },[entity])

    return(
        <div className="entity h-screen w-fit">
            <div className="flex flex-col w-full sm:flex-row">
                <div className="flex-1">
                    {(entity.cover_url) ? <img className="lg:w-2/5 md:h-full md:w-2/3 h-3/5 w-4/5 border-4 hover:border-8 border-cyan-500 object-cover mx-auto mt-40 shadow-lg shadow-cyan-500/50 hover:shadow-cyan-500/90" src={`${config.ImageServer}/image/${entity.cover_url}`}/>:<div></div> }
                </div>
                <div className="flex-1 flex h-80 flex-col sm:mt-40 mt-20 sm:mx-auto mx-5">
                    <p className="flex-1 lg:text-5xl md:text-4xl sm:text-3xl font-jetbrains font-bold tracking-wide uppercase text-center text-xl text-gray-400 mr-5">{entity.title}</p>
                    <p className="flex-1 lg:text-2xl md:text-xl sm:text-lg text-base font-jetbrains text-gray-300 mr-5 mt-10">{entity.description}</p>
                    <div className="ml-5 mt-10">
                    {comps}
                    </div>
                </div>
            </div>
        </div>
    )
}

export default Entity
like image 270
Vishnu Haasan Avatar asked Oct 16 '25 21:10

Vishnu Haasan


1 Answers

To change the URL, by the input the user enters, you can use this code

import { useState } from 'react'
import { Link } from "react-router-dom";

function App() {
  const [URL, setURL] = useState('#');
  const handleSearch = (event) => {
    setURL(event.target.value)
  }
  return (
    <div>
      <input onChange={handleSearch}></input>
      <Link to={URL}>click me!</Link>
    </div>
  );
}
export default App;
like image 120
Miryam Oren Avatar answered Oct 19 '25 10:10

Miryam Oren



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!