skip to Main Content

I am writing a simple web app in React.

I’m trying to send data from one page to another using the useLocation hook in React Router, and I can’t seem to pass the data. For some reason, despite the value of un changing, as shown by console logs, when I pass un as a state to "/link-page", the value is passed as if no changes have been made. That is, the username displayed on the link page is simply 'h'.

Here is my code:

Home.jsx:

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

let un = 'h'

function handleChange() {
    un = document.getElementById("username").value;
}

function Home() {
    return (
        <>
            <h1>welcome to duel.fm!</h1>
            <h3>enter your last.fm username below</h3>
            <form>
                <input type={"text"} id={"username"} onChange={handleChange} />
                <Link to={"/link-page"} state={{ username: un }}>
                    <input type={"submit"} value={"submit"} />
                </Link>
            </form>
        </>
    )
}

export default Home;

LinkPage.jsx:

import { useLocation } from 'react-router-dom';

function LinkPage() {
    const location = useLocation();
    const username = location.state.username;

    return (
        <>
            <h3>share this link with your friend!</h3>
            <h5>{username}</h5>
        </>
    )
}

export default LinkPage;

2

Answers


  1. Chosen as BEST ANSWER

    Got it.

    React doesn't care about the value of un, only the states of certain variables. Fixed it by using useState().


  2. Issue

    un and handleChange are declared outside the ReactTree, so no updates to h will trigger React to rerender the Home component so that a new "instance" of handleChange is used with the updated un value.

    The form submission will also reload the page, so you’ll want to address that so that the data passed via the link persists through to the target route.

    Solution

    Move un and handleChange into the Home component as React state and callback. The input should be fully controlled using the new state and setting a value prop. handleChange should read the input value from the onChange event object instead of using document.getElementById which is considered a React anti-pattern.

    Make the form button not a submit button.

    import { useState } from 'react';
    import { Link } from "react-router-dom";
    
    function Home() {
      const [username, setUsername] = useState("h");
    
      function handleChange(e) {
        setUsername(e.target.value);
      }
    
      return (
        <>
          <h1>welcome to duel.fm!</h1>
          <h3>enter your last.fm username below</h3>
          <form>
            <input
              type="text"
              id="username"
              onChange={handleChange}
              value={username}
            />
            <Link to="/link-page" state={{ username }}>
              <button type="button">Link Page</button>
            </Link>
          </form>
        </>
      );
    }
    

    If you wanted to use the form submission to navigate, then I’d recommend using the useNavigate hook and issuing a declarative navigation action.

    Example:

    import { useState } from 'react';
    import { useNavigate } from "react-router-dom";
    
    function Home() {
      const [un, setUn] = useState("h");
    
      function handleChange(e) {
        setUsername(e.target.value);
      }
    
      function onSubmit(e) {
        e.preventDefault(); // don't submit form & reload page
        navigate("/link-page", { state: { username } });
      }
    
      return (
        <>
          <h1>welcome to duel.fm!</h1>
          <h3>enter your last.fm username below</h3>
          <form onSubmit={onSubmit}>
            <input
              type="text"
              id="username"
              onChange={handleChange}
              value={username}
            />
            <button type="submit">Link Page</button>
          </form>
        </>
      );
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search