mui / material-ui

Material UI: Comprehensive React component library that implements Google's Material Design. Free forever.
https://mui.com/material-ui/
MIT License
93.67k stars 32.22k forks source link

[material-ui][Autocomplete] React keys being passed directly to JSX without using spread #41486

Closed Chukwu3meka closed 7 months ago

Chukwu3meka commented 7 months ago

Steps to reproduce


import Ellipsis from "components/shared/ellipsis";

import { SearchOutlined as SearchIcon } from "@mui/icons-material";
import { SearchProps } from "interfaces/components/apihub.interface";
import { TextField, Autocomplete, Divider, Stack, Typography, Box, IconButton } from "@mui/material";

const Search = ({ searchResult, onInputChange, onValueChange, value, inputValue, getEndpoint, isOptionEqualToValue }: SearchProps) => (
  <Autocomplete
    fullWidth
    value={value}
    options={searchResult}
    inputValue={inputValue}
    onChange={(e, newValue) => onValueChange(newValue)}
    onInputChange={(e, newInputValue) => onInputChange(newInputValue)}
    filterOptions={(options) => options} // Return all options without filtering
    isOptionEqualToValue={(option, value) => isOptionEqualToValue(option, value)}
    getOptionLabel={(option) => (typeof option === "string" ? inputValue : option.title)}
    renderOption={(props, { title, description, id }) => (
      <Box component="li" mb={1} {...props}>
        <Stack onClick={() => getEndpoint(id)}>
          <Stack direction="row" justifyContent="space-between" alignItems="flex-end" spacing={1} sx={{ width: "100%" }}>
            <Typography maxWidth="80%" fontSize=".8em" noWrap sx={{ textTransform: "uppercase" }}>
              {title}
            </Typography>
          </Stack>

          <Divider sx={{ width: "90%", my: 1, alignSelf: "flex-end" }} />

          <Ellipsis lines={2} display="block" variant="caption" color="text.secondary" sx={{ mt: 0.5, ml: 2 }}>
            {description}
          </Ellipsis>
        </Stack>
      </Box>
    )}
    // renderInput={(params) => <TextField {...params} placeholder="Start typing to search" inputProps={{ ...params.inputProps }} />}

    renderInput={(params) => (
      <TextField
        sx={{ mt: 2 }}
        {...params}
        label={
          <Stack direction="row">
            <IconButton aria-label="mongodb" component="span" sx={{ mt: -1 }}>
              <SearchIcon />
            </IconButton>
            Start typing to search endpoints
          </Stack>
        }
      />
    )}
  />
);

export default Search;

Current behavior

Error happens once server returns matching results. Adding key to <Box component="li" mb={1} {...props}> does not solve the issue

Expected behavior

No response

Context

Warning: A props object containing a "key" prop is being spread into JSX: let props = {key: someKey, component: ..., mb: ..., tabIndex: ..., role: ..., id: ..., onMouseMove: ..., onClick: ..., onTouchStart: ..., data-option-index: ..., aria-disabled: ..., aria-selected: ..., className: ..., children: ...}; <ForwardRef(Box) {...props} /> React keys must be passed directly to JSX without using spread: let props = {component: ..., mb: ..., tabIndex: ..., role: ..., id: ..., onMouseMove: ..., onClick: ..., onTouchStart: ..., data-option-index: ..., aria-disabled: ..., aria-selected: ..., className: ..., children: ...}; <ForwardRef(Box) key={someKey} {...props} /> at Autocomplete (webpack-internal:///(app-pages-browser)/./node_modules/@mui/material/Autocomplete/Autocomplete.js:511:85) at Search (webpack-internal:///(app-pages-browser)/./components/apihub/search/Search.tsx:17:11) at SearchContainer (webpack-internal:///(app-pages-browser)/./components/apihub/search/SearchContainer.tsx:13:11) at div at eval (webpack-internal:///(app-pages-browser)/./node_modules/@emotion/react/dist/emotion-element-43c6fea0.browser.esm.js:60:66) at Box (webpack-internal:///(app-pages-browser)/./node_modules/@mui/system/esm/createBox.js:36:76) at div at eval (webpack-internal:///(app-pages-browser)/./node_modules/@emotion/react/dist/emotion-element-43c6fea0.browser.esm.js:60:66) at Grid (webpack-internal:///(app-pages-browser)/./node_modules/@mui/system/esm/Stack/createStack.js:160:24) at div at eval (webpack-internal:///(app-pages-browser)/./node_modules/@emotion/react/dist/emotion-element-43c6fea0.browser.esm.js:60:66) at Box (webpack-internal:///(app-pages-browser)/./node_modules/@mui/system/esm/createBox.js:36:76) at div at eval (webpack-internal:///(app-pages-browser)/./node_modules/@emotion/react/dist/emotion-element-43c6fea0.browser.esm.js:60:66) at Grid (webpack-internal:///(app-pages-browser)/./node_modules/@mui/material/Grid/Grid.js:387:89) at div at eval (webpack-internal:///(app-pages-browser)/./node_modules/@emotion/react/dist/emotion-element-43c6fea0.browser.esm.js:60:66) at Grid (webpack-internal:///(app-pages-browser)/./node_modules/@mui/material/Grid/Grid.js:387:89) at div at eval (webpack-internal:///(app-pages-browser)/./node_modules/@emotion/react/dist/emotion-element-43c6fea0.browser.esm.js:60:66) at Box (webpack-internal:///(app-pages-browser)/./node_modules/@mui/system/esm/createBox.js:36:76) at EndpointsIntro (webpack-internal:///(app-pages-browser)/./components/apihub/endpoints/EndpointsIntro.tsx:18:11) at main at EndpointsContainer (webpack-internal:///(app-pages-browser)/./components/apihub/endpoints/EndpointsContainer.tsx:17:92) at ConnectFunction (webpack-internal:///(app-pages-browser)/./node_modules/react-redux/dist/react-redux.mjs:875:74) at InnerLayoutRouter (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js:242:11) at RedirectErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/redirect-boundary.js:73:9) at RedirectBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/redirect-boundary.js:81:11) at NotFoundBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/not-found-boundary.js:84:11) at LoadingBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js:340:11) at ErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/error-boundary.js:161:11) at InnerScrollAndFocusHandler (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js:152:9) at ScrollAndFocusHandler (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js:227:11) at RenderFromTemplateContext (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/render-from-template-context.js:16:44) at OuterLayoutRouter (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js:359:11) at InnerLayoutRouter (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js:242:11) at RedirectErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/redirect-boundary.js:73:9) at RedirectBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/redirect-boundary.js:81:11) at NotFoundBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/not-found-boundary.js:84:11) at LoadingBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js:340:11) at ErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/error-boundary.js:161:11) at InnerScrollAndFocusHandler (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js:152:9) at ScrollAndFocusHandler (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js:227:11) at RenderFromTemplateContext (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/render-from-template-context.js:16:44) at OuterLayoutRouter (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js:359:11) at div at ApiHubLayout (webpack-internal:///(app-pages-browser)/./components/layouts/apihub-layout/ApihubLayout.tsx:11:11) at InnerLayoutRouter (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js:242:11) at RedirectErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/redirect-boundary.js:73:9) at RedirectBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/redirect-boundary.js:81:11) at NotFoundErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/not-found-boundary.js:76:9) at NotFoundBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/not-found-boundary.js:84:11) at Suspense at LoadingBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js:340:11) at ErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/error-boundary.js:161:11) at InnerScrollAndFocusHandler (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js:152:9) at ScrollAndFocusHandler (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js:227:11) at RenderFromTemplateContext (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/render-from-template-context.js:16:44) at OuterLayoutRouter (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js:359:11) at SWRConfig (webpack-internal:///(app-pages-browser)/./node_modules/swr/dist/_internal/index.mjs:571:13) at ThemeProvider (webpack-internal:///(app-pages-browser)/./node_modules/@mui/private-theming/ThemeProvider/ThemeProvider.js:42:5) at ThemeProvider (webpack-internal:///(app-pages-browser)/./node_modules/@mui/system/esm/ThemeProvider/ThemeProvider.js:59:13) at Providers (webpack-internal:///(app-pages-browser)/./components/providers/Providers.tsx:19:11) at ProvidersContainer (webpack-internal:///(app-pages-browser)/./components/providers/ProvidersContainer.tsx:20:13) at ConnectFunction (webpack-internal:///(app-pages-browser)/./node_modules/react-redux/dist/react-redux.mjs:875:74) at SnackbarProvider (webpack-internal:///(app-pages-browser)/./node_modules/notistack/notistack.esm.js:1491:24) at Provider (webpack-internal:///(app-pages-browser)/./node_modules/react-redux/dist/react-redux.mjs:1049:3) at AppRouterCacheProvider (webpack-internal:///(app-pages-browser)/./node_modules/@mui/material-nextjs/v13-appRouter/appRouterV13.js:26:13) at RootProviders (webpack-internal:///(app-pages-browser)/./components/providers/RootProviders.tsx:19:11) at body at html at RedirectErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/redirect-boundary.js:73:9) at RedirectBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/redirect-boundary.js:81:11) at NotFoundErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/not-found-boundary.js:76:9) at NotFoundBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/not-found-boundary.js:84:11) at DevRootNotFoundBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/dev-root-not-found-boundary.js:33:11) at ReactDevOverlay (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/react-dev-overlay/internal/ReactDevOverlay.js:84:9) at HotReload (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/react-dev-overlay/hot-reloader-client.js:307:11) at Router (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/app-router.js:182:11) at ErrorBoundaryHandler (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/error-boundary.js:114:9) at ErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/error-boundary.js:161:11) at AppRouter (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/app-router.js:538:13) at ServerRoot (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/app-index.js:129:11) at RSCComponent at Root (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/app-index.js:145:11)

Your environment

npx @mui/envinfo ``` Don't forget to mention which browser you used. Browser used is chrome Output from `npx @mui/envinfo` goes here. System: OS: Windows 11 10.0.22631 Binaries: Node: 20.10.0 - C:\Program Files\nodejs\node.EXE npm: 10.2.5 - C:\Program Files\nodejs\npm.CMD pnpm: Not Found Browsers: Chrome: Not Found Edge: Chromium (122.0.2365.80) npmPackages: @emotion/react: ^11.11.4 => 11.11.4 @emotion/styled: ^11.11.0 => 11.11.0 @mui/base: 5.0.0-beta.38 @mui/core-downloads-tracker: 5.15.12 @mui/icons-material: ^5.15.12 => 5.15.12 @mui/lab: ^5.0.0-alpha.167 => 5.0.0-alpha.167 @mui/material: ^5.15.12 => 5.15.12 @mui/material-nextjs: ^5.15.11 => 5.15.11 @mui/private-theming: 5.15.12 @mui/styled-engine: 5.15.11 @mui/system: ^5.15.12 => 5.15.12 @mui/types: 7.2.13 @mui/utils: 5.15.12 @types/react: ^18 => 18.2.47 react: ^18.2.0 => 18.2.0 react-dom: ^18.2.0 => 18.2.0 typescript: ^5 => 5.3.3 ```

Search keywords: next.js autocomplete

danilo-leal commented 7 months ago

Hey @Chukwu3meka; thanks for opening the issue! Can you provide a reproducible CodeSandbox for better troubleshooting?

mj12albert commented 7 months ago

Adding key to <Box component="li" mb={1} {...props}> does not solve the issue

Is this what you tried? <Box component="li" mb={1} {...props} key={props.key}> @Chukwu3meka

bmorales-broditec commented 7 months ago

Hi, I have the same issue. I tried @mj12albert's suggestion but it doesn't work for me.

Some of the implementations I have tried and have the same problem:

First

<li {...props}>

// Error
Warning: A props object containing a "key" prop is being spread into JSX:
  let props = {key: someKey, tabIndex: ..., role: ..., id: ..., onMouseMove: ..., onClick: ..., onTouchStart: ..., data-option-index: ..., aria-disabled: ..., aria-selected: ..., className: ..., children: ...};
  <li {...props} />
React keys must be passed directly to JSX without using spread:
  let props = {tabIndex: ..., role: ..., id: ..., onMouseMove: ..., onClick: ..., onTouchStart: ..., data-option-index: ..., aria-disabled: ..., aria-selected: ..., className: ..., children: ...};
  <li key={someKey} {...props} />

Second

<li key={option.id} {...props}>

// Same error

Third

<li {...props} key={option.id}>

// Error
Warning: Each child in a list should have a unique "key" prop. See https://reactjs.org/link/warning-keys for more information.
But I don't have element with repeated id

Fourth

renderOption={(props, option, { selected }) => {
    const customKey = `${option.id} ${option.name}`
    return (
        <li key={customKey} {...props}>

 // Same error

Code

<Autocomplete
  disableCloseOnSelect
  fullWidth
  getOptionLabel={(option) => option.name}
  groupBy={(option) => option.wellnessArea.name}
  multiple
  options={getWellnessCategoriesData?.getWellnessCategories || []}
  renderInput={(params) => (
    <TextField
      {...params}
      helperText={
        t.completeProfilePage.wellnessCategories.categoriesHelperText
      }
      label={t.completeProfilePage.wellnessCategories.categoriesLabel}
      placeholder={
        t.completeProfilePage.wellnessCategories.categoriesPlaceholder
      }
      variant="outlined"
    />
  )}
  renderOption={(props, option, { selected }) => (
    <li key={option.id} {...props}>
      <Checkbox
        checked={selected}
        checkedIcon={checkedIcon}
        icon={icon}
        style={{ marginRight: 8 }}
      />
      {option.name}
    </li>
  )}
  size="medium"
/>
github-actions[bot] commented 7 months ago

Since the issue is missing key information and has been inactive for 7 days, it has been automatically closed. If you wish to see the issue reopened, please provide the missing information.