Home > Enterprise >  How to get a value from a dropdown menu in a navbar to my other components in react
How to get a value from a dropdown menu in a navbar to my other components in react

Time:07-26

I am trying to put in an impersonate feature on my project with a dropdown menu in my nav bar. I am pulling the navbar component into my app.js file so it renders on every page.

  <div className="App">
    <NavBar />
    <BrowserRouter>
      <Routes>
        <Route path='/' element={<Home />} />
        <Route path='/Buckets' element={<Buckets />} />
        <Route path='/Tables' element={<Tables />} />
      </Routes>
    </BrowserRouter>
  </div>

Below is my navbar which makes a fetch call to get the list of users and sends it down to the userList component through a prop.

    const users = useFetch("http://localhost:8000/Users")
return (
    <nav className='NavBar'>
        <h1>POC</h1>
        {users && <UserList Users={users}/>}
        <div className="Links">
            <a href="/">Home</a>
            <a href="/Buckets">Buckets</a>
            <a href="/Tables">Tables</a>
        </div>
    </nav>
);

Then in my userList.js file I am taking that object mapping it and dynamically filling the dropdown menu and setting the state.

const UserList = ({Users}) => {
let optionTemplate = Users.map(v => (
    <option value={v.id}>{v.user}</option>
  ));
  const [value, setValue] = useState('user1');

function handleClick() {
    console.log('clicked')
}

return (
    <div className="dropdown">
        <label className='label'>
        Account: 
            <select value={value} onChange={(e) => setValue(e.target.value)}>
                {optionTemplate}
            </select>
        </label>
        <button onClick={handleClick}>Login</button>
    </div>
);

The issue I am having is that when I navigate to my buckets page, or to any page the dropdown resets to the default value of user1. Which makes sense since that is the default state of the page. (that is another question for another day to persist) But this one is how do I get the value of the dropdown to be passed to sibling components. For instance the buckets page should make an API call based on the user that is currently selected by the drop down.

CodePudding user response:

This is a common problem that is solved by lifting state up:

Often, several components need to reflect the same changing data. We recommend lifting the shared state up to their closest common ancestor.

One way to solve this without manually passing props down into every single component is by using React Contexts. Either way, you will need to store the actual dropdown state in app.js or something even further up the tree. Other data store models like Redux are options too, depending on the needs of the rest of your app.

CodePudding user response:

If you don't want to use Redux then You can move the drop-down selection value state in the Navbar component and pass it as a prop to the Userlist component.

Navbar.js

const NavBar = () => {
  const [value, setValue] = useState("user1");
  const setUser = (user) => setValue(user);
  const users = useFetch("http://localhost:8000/Users");
  return (
    <nav className="NavBar">
      <h1>POC</h1>
      {users && <UserList Users={users} user={value} setUser={setUser} />}
      <div className="Links">
        <a href="/">Home</a>
        <a href="/Buckets">Buckets</a>
        <a href="/Tables">Tables</a>
      </div>
    </nav>
  );
};

UserList.js

const UserList = ({ Users, user, setUser }) => {
  let optionTemplate = Users.map((v) => <option value={v.id}>{v.user}</option>);

  return (
    <div className="dropdown">
      <label className="label">
        Account:
        <select value={user} onChange={(e) => setUser(e.target.value)}>
          {optionTemplate}
        </select>
      </label>
      <button onClick={handleClick}>Login</button>
    </div>
  );
};
  • Related