Home > Net >  Getting <Select> defaultValue to set from a state. React MUI
Getting <Select> defaultValue to set from a state. React MUI

Time:03-29

I've been working on this one bug for a couple of days and cannot find anything that will fix it.

What I'm attempting to do is populate the pre-selected value that comes from the local storage and connects with fetch request data. The select request data populates as the menu options and the default select should be saved locally so when the user refreshed or leaves the comes back, their league is still selected.

I'm getting the data to send in console.log() when it renders, but it will not populate the <Select default={currentLeague}>.

Here's my code in question:

import React, { useState, useEffect } from  "react";

import { 
AppBar, Toolbar, Tabs, Tab, Button, Box, Menu, MenuItem, Divider, Typography, Grid, Select, FormControl, } from '@mui/material';

export default function NavBar(props){
    const [leagues, setLeagues] = useState([]);
    const [currentLeague, setCurrentLeague] = useState()

    useEffect(() => {
        getLeagues();
        setCurrentLeague(JSON.parse(localStorage.getItem('currentLeague')));
     }, []);

    const getLeagues = () => {
        fetch('/draft/get-user-leagues')
            .then((response) => response.json())
            .then((data) => {
                setLeagues(data)
            })
    }

    function handleLeagueChange(e) {
        localStorage.setItem('currentLeague', JSON.stringify(e.target.value));
    }   

    function leagueDropdown(leagues) {
        if (leagues.length === 0) {
            return (<Button
                    component={Link}
                    to='/create-league'
                    >
                        Create New League <AddCircleIcon sx={{marginLeft:'10px'}}/>
                    </Button>
            )
        } else {
        console.log("current League: "   currentLeague.name);
        console.log(currentLeague)
        return (
            <Select
                defaultValue={currentLeague}
                onChange={handleLeagueChange}
            >
                {leagues.map((league, index) => {
                    return <MenuItem 
                                value={league}
                            > 
                                {league.name}
                            </MenuItem>
                })}
            </Select>
        )
    }

    return (
    <AppBar>
        <Toolbar>
            <FormControl>
                {leagueDropdown(leagues)}
            </FormControl>
        </Toolbar>
    </AppBar>
    )
}

I can get the defaultValue to populate if I manually put in 'leagues[1]' but I cannot populate it using currentLeague.

Any advice would be appreciated!

Edit to add the response:

    [
  {
    "name": "TestLeague2",
    "owner": "0e31ac27-8978-49cb-81e0-fa6259bdad2b",
    "year": 2022,
    "id": 1
  },
  {
    "name": "TestLeague2",
    "owner": "0e31ac27-8978-49cb-81e0-fa6259bdad2b",
    "year": 2022,
    "id": 2
  },
  {
    "name": "TestLeague2",
    "owner": "0e31ac27-8978-49cb-81e0-fa6259bdad2b",
    "year": 2022,
    "id": 3
  },
  {
    "name": "TestLeague55",
    "owner": "0e31ac27-8978-49cb-81e0-fa6259bdad2b",
    "year": 2022,
    "id": 4
  },
  {
    "name": "TestLeague55",
    "owner": "0e31ac27-8978-49cb-81e0-fa6259bdad2b",
    "year": 2022,
    "id": 5
  },
  {
    "name": "Jacob's League",
    "owner": "0e31ac27-8978-49cb-81e0-fa6259bdad2b",
    "year": 2022,
    "id": 6
  },
  {
    "name": "test234",
    "owner": "0e31ac27-8978-49cb-81e0-fa6259bdad2b",
    "year": 2022,
    "id": 7
  },
  {
    "name": "teasdf",
    "owner": "0e31ac27-8978-49cb-81e0-fa6259bdad2b",
    "year": 2022,
    "id": 8
  },
  {
    "name": "teasdf",
    "owner": "0e31ac27-8978-49cb-81e0-fa6259bdad2b",
    "year": 2022,
    "id": 9
  },
  {
    "name": "teasdf",
    "owner": "0e31ac27-8978-49cb-81e0-fa6259bdad2b",
    "year": 2022,
    "id": 10
  },
  {
    "name": "please1",
    "owner": "0e31ac27-8978-49cb-81e0-fa6259bdad2b",
    "year": 2022,
    "id": 11
  }
]

CodePudding user response:

Use the currentLeague state and actually fully control the select input. Use the value prop instead of the defaultValue prop that you are trying to change after the initial render.

You can initialize the currentLeague state directly from localStorage. Enqueue normal React state updates in the onChange handler and use an useEffect hook to persist the state changes to localStorage.

You can't use object for the select input's option values, so I suggest using the league.id property as the select value.

Example:

export default function NavBar(props){
  const [leagues, setLeagues] = useState([]);
  const [currentLeague, setCurrentLeague] = useState(
    JSON.parse(localStorage.getItem('currentLeague')) || ''
  );

  useEffect(() => {
    getLeagues();
  }, []);

  useEffect(() => {
    localStorage.setItem('currentLeague', JSON.stringify(currentLeague));
  }, [currentLeague]);

  const getLeagues = () => {
    fetch('/draft/get-user-leagues')
      .then((response) => response.json())
      .then((data) => {
        setLeagues(data)
      });
  };

  function handleLeagueChange(e) {
    setCurrentLeague(e.target.value);
  }   

  function leagueDropdown(leagues) {
    if (leagues.length === 0) {
      return (
        <Button component={Link} to='/create-league'>
          Create New League <AddCircleIcon sx={{marginLeft:'10px'}}/>
        </Button>
      )
    } else {
      return (
        <Select
          value={currentLeague}
          onChange={handleLeagueChange}
        >
          {leagues.map((league, index) => (
            <MenuItem key={league.id} value={league.id}> 
              {league.name}
            </MenuItem>
          ))}
        </Select>
      );
    }
  }

  return (
    <AppBar>
      <Toolbar>
        <FormControl>
          {leagueDropdown(leagues)}
        </FormControl>
      </Toolbar>
    </AppBar>
  );
}

Edit getting-select-defaultvalue-to-set-from-a-state-react-mui

  • Related