0

I'm passing JSON data pulled off a REST API via props to the component below. Since I don't pre-set a value to the "Pick a team" select field, it outputs the following warning:

MUI: You have provided an out-of-range value undefined for the select component. Consider providing a value that matches one of the available options or ''.

which is normal, because there isn't a selected value.

How can I add skeleton effect to the form below until the props data is loaded?

<Skeleton variant="text" />
<Skeleton variant="circular" width={40} height={40} />
<Skeleton variant="rectangular" width={210} height={118} />

FormOne.tsx

import {
  Box,
  Button,
  FormControl,
  Grid,
  InputLabel,
  MenuItem,
  Select,
  SelectChangeEvent,
  Typography,
} from '@mui/material';
import { useState } from 'react';

import { TeamSeason as Team } from './lib/interfaces/TeamSeason';

const FormOne = (props: any) => {
  const [selectedTeam, setSelectedTeam] = useState<Team | null>(null);
  const [selectedQuery, setSelectedQuery] = useState<number>(1);

  const handleQueryChange = (event: SelectChangeEvent) => {
    setSelectedQuery(Number(event.target.value));
  };

  const handleTeamChange = (event: SelectChangeEvent) => {
    const team = props.data.find(
      (team: Team) => team.statId === Number(event.target.value)
    );
    setSelectedTeam(team);
  };

  return (
    <>
      <Box mb={2}>
        <Typography component="h1" variant="h4" align="center">
          GUI #1
        </Typography>
      </Box>

      <Box component="form" noValidate autoComplete="off">
        <Grid container spacing={2}>
          <Grid item xs={12}>
            <FormControl variant="outlined" fullWidth>
              <InputLabel id="team-label">Pick a team</InputLabel>
              <Select
                labelId="team-label"
                id="team"
                value={selectedTeam?.id?.toString()}
                onChange={handleTeamChange}
              >
                {props.data.map((team: Team) => {
                  return (
                    <MenuItem key={team.statId} value={team.statId.toString()}>
                      {team.name} ({team.team})
                    </MenuItem>
                  );
                })}
              </Select>
            </FormControl>
          </Grid>

          <Grid item xs={12}>
            <FormControl variant="outlined" fullWidth>
              <InputLabel id="query-label">Query</InputLabel>
              <Select
                labelId="query-label"
                id="query"
                value={selectedQuery.toString()}
                onChange={handleQueryChange}
              >
                <MenuItem value={1}>What name does he use?</MenuItem>
                <MenuItem value={2}>What abbreviature does he have?</MenuItem>
              </Select>
            </FormControl>
          </Grid>

          <Grid item xs={12}>
            <Button variant="contained">Submit</Button>
          </Grid>

          <Grid item xs={12}>
            {selectedTeam && selectedQuery === 1 && (
              <p>team name: {`${selectedTeam?.name}`}</p>
            )}
            {selectedTeam && selectedQuery === 2 && (
              <p>team abbreviature: {`${selectedTeam?.team}`}</p>
            )}
          </Grid>
        </Grid>
      </Box>
    </>
  );
};

export default FormOne;

index.tsx

import { useState, useEffect } from 'react';
import type { NextPage } from 'next';
import Container from '@mui/material/Container';
import Box from '@mui/material/Box';
import { DataGrid, GridColDef } from '@mui/x-data-grid';
import { Grid, Paper } from '@mui/material';
import Skeleton from '@mui/material/Skeleton';
import { blue } from '@mui/material/colors';

import FormOne from './../src/FormOne';

const LoadingSkeleton = () => (
  <Box
    sx={{
      height: 'max-content',
    }}
  >
    {[...Array(10)].map((_, index) => (
      <Skeleton variant="rectangular" sx={{ my: 4, mx: 1 }} key={index} />
    ))}
  </Box>
);

const columns: GridColDef[] = [
  { field: 'statId', headerName: 'Stat ID' },
  { field: 'name', headerName: 'Name', width: 200 },
  { field: 'season', headerName: 'Season' },
];

const Home: NextPage = () => {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    setInterval(
      () =>
        fetch('https://localhost:7000/TeamSeason/2021')
          .then((response) => response.json())
          .then((data) => {
            setData(data);
            setLoading(false);
          }),
      3000
    );
  }, []);

  return (
    <Container
      maxWidth={false}
      sx={{
        height: '100vh',
        overflow: 'auto',
        background: `linear-gradient(to right, ${blue[200]}, ${blue[500]})`,
      }}
    >
      <Container maxWidth="lg" sx={{ mt: 3, mb: 3 }}>
        <Grid container spacing={{ xs: 2, md: 3 }}>
          <Grid item xs={12} md={6}>
            <Paper sx={{ padding: 3 }}>
              <FormOne data={data} />
            </Paper>
          </Grid>

          <Grid item xs={12} md={6}>
            <Paper sx={{ padding: 3 }}></Paper>
          </Grid>

          <Grid item xs={12}>
            <Paper sx={{ padding: 3 }}>
              <DataGrid
                getRowId={(row) => row.statId}
                sx={{ height: '650px' }} // either autoHeight or this
                rows={data}
                columns={columns}
                pageSize={10}
                // autoHeight
                rowsPerPageOptions={[10]}
                disableSelectionOnClick
                disableColumnMenu
                disableColumnSelector
                components={{
                  LoadingOverlay: LoadingSkeleton,
                }}
                loading={loading}
              />
            </Paper>
          </Grid>
        </Grid>
      </Container>
    </Container>
  );
};

export default Home;

CodeSandbox

nop
  • 4,711
  • 6
  • 32
  • 93

0 Answers0