Home > database >  React Router Link component not rendering when redirect
React Router Link component not rendering when redirect

Time:07-25

I'm using the material-ui library's component Autocomplete with React flux to create a Search Bar that finds users.

I want every option to be a link to a page with more information of that user. Currently, it only works the first time I click on an option. Every time after that it changes the URL but the page is not re-rendered.

This is the Autocomplete code:

export function SearchBar() {
  const [url, setUrl] = useState("/perfil/");

  const { store, actions } = useContext(Context);

  useEffect(() => {
    actions.search();
  }, [url]);

  const artistas = store.artistas.slice();

  return (
    <Autocomplete
      id="autocomplete"
      freeSolo
      disableClearable
      options={artistas}
      getOptionLabel={(option) => option.nombre   " "   option.apellido}
      renderOption={(option) => (
        <Link
          className="text-black text-decoration-none"
          onClick={() => setUrl(url   option.id)}
          to={`/perfil/${option.id}`}
        >
          {option.nombre} {option.apellido}
        </Link>
      )}
      renderInput={(params) => (
        <TextField
          {...params}
          size="small"
          placeholder="Search for your artist"
          margin="normal"
          variant="outlined"
          InputProps={{ ...params.InputProps, type: "search" }}
        />
      )}
    />
  );
}

This is the page where it is redirected:

export const Perfil = () => {
  const { user_id } = useParams();

  return (
    <>
        <About user_id={user_id} />
        <Galeria user_id={user_id} />
    </>
  );
};

The flux action is this:

  search: async () => {
        try {
          const response = await fetch(
            process.env.BACKEND_URL   "/api/artistas"
          );
          const data = await response.json();
          setStore({
            artistas: data,
          });
        } catch (error) {
          console.log("Error loading message from /api/artistas", error);
        }
      }

At last, this is the layout page:

return (
    <div>
      <BrowserRouter basename={basename}>
        <ScrollToTop>
          <Navbar />
          <Routes>
            <Route element={<Inicio />} path="/" />
            <Route element={<Login />} path="/login" />
            <Route element={<Registro />} path="/registro" />
            <Route element={<Perfil />} path="/perfil/:user_id" />
            <Route element={<Producto />} path="/producto/:theid" />
            <Route
              element={<ConfiguracionUsuario />}
              path="/configuracion/:theid"
            />
            <Route element={<h1> Not found! </h1>} />
          </Routes>{" "}
          <Footer />
        </ScrollToTop>{" "}
      </BrowserRouter>{" "}
    </div>
  );

CodePudding user response:

Link tags work first move to url. After that onClick logic will start after moved link. So if you want to use Link tag with onClick then i recommend two ways.

  1. react-router-dom v5 or lower : just don't use 'to' property and just use onClick and in the onClick property you can use useHistory hook inside onClick. You can use under 2. Option here too.
  2. react-router-dom v6 or lower : use 'a' tag with onClick property you can use useNavigate hook inside onClick.

CodePudding user response:

I fixed it. The problem was in the Galeria component. It took the id by props:

  useEffect(() => {
    actions.producto_galeria(props.user_id);
  }, []);

But we should have used a stored variable with the ID that changes on every click with a flux action, instead of props. So now, I get the ID as follows:

flux new action:

get_artista_id: (artista_id) => {
    setStore({ artista_id: artista_id });
}

Link new onClick:

 <Link
  className="text-black text-decoration-none"
  onClick={() => {
    actions.get_artista_id(option.id);
  }}
  to={`/perfil/${option.id}`}
>
  {option.nombre} {option.apellido}
</Link>

useEffect on Galeria to detect the change on the ID:

  useEffect(() => {
    actions.producto_galeria(store.artista_id);
  }, [store.artista_id]);
  • Related