Material UI V5 <ListItemButton> onClick 不工作

Material UI V5 <ListItemButton> onClick not working

我使用 Link API 创建了一个搜索建议列表。但是 onClick 处理程序没有按预期触发。我应该如何更正它?

这是我的列表代码

<Paper
      elevation={5}
      sx={{ maxWidth: { xs: "100%", md: "45%" }, marginTop: "10px" }}
    >
      <List sx={{ paddingTop: "20px", paddingBottom: "30px" }}>
        {topResponses.map((response, index) => {
          return (
            <>
              <ListItemButton
                id={response}
                sx={{
                  paddingTop: "20px",
                  paddingBottom: "10px",
                  border: "2px solid red",
                }}
                onClick={(event) => {
                  console.log("clicked");
                  
                }}
              >
                <ListItemText
                  primary={response}
                  primaryTypographyProps={{
                    fontSize: "18px",
                    fontWeight: "bold",
                  }}
                />
                {/* <p>{response}</p> */}
              </ListItemButton>
              <Divider variant="middle" textAlign="center" />
            </>
          );
        })}
      </List>
    </Paper>

一件事可能是因为它是一个搜索建议,我设置了一个处理程序,一旦焦点从搜索栏中消失就会触发。所以当我点击搜索建议时,它应该被触发。这会是问题所在吗?

我想我遇到了问题。当搜索栏上的焦点发生变化时,我有一个焦点处理程序可以切换 on/off。据我所知,当我单击搜索建议时,此焦点处理程序会触发 re-render 而根本不会触发 onClick 函数。]

我通过在焦点处理程序上添加 100ms-200ms 的 setTimeout 来稍微延迟它来解决这个问题,这就成功了。

有人知道更好的处理方法吗?

P.S 这是我的完整代码

import React from "react";
import {
  Paper,
  Box,
  TextField,
  Button,
  ListItemText,
  List,
  Divider,
  ListItemButton,
} from "@mui/material";
import { useState, useRef } from "react";

const topResponses = ["HTML", "Senior", "Junior", "React", "CSS"];
const searchSuggestions = [
  "Fullstack",
  "Midweight",
  "Python",
  "React",
  "JavaScript",
  "Sass",
  "CSS",
  "Backend",
  "Junior",
  "Ruby",
  "RoR",
  "HTML",
  "Frontend",
  "Vue",
  "Django",
];

const TopSuggestions = ({ filterHandler }) => {
  return (
    <Paper
      elevation={5}
      sx={{ maxWidth: { xs: "100%", md: "45%" }, marginTop: "10px" }}
    >
      <List sx={{ paddingTop: "20px", paddingBottom: "30px" }}>
        {topResponses.map((response, index) => {
          return (
            <>
              <ListItemButton
                key={index}
                sx={{
                  paddingTop: "20px",
                  paddingBottom: "10px",
                }}
                onClick={(event) => {
                  console.log("top suggestion clicked")
                  filterHandler(event.target.textContent);
                }}
              >
                <ListItemText
                  primary={response}
                  primaryTypographyProps={{
                    fontSize: "18px",
                    fontWeight: "bold",
                  }}
                />
                {/* <p>{response}</p> */}
              </ListItemButton>
              <Divider variant="middle" textAlign="center" />
            </>
          );
        })}
      </List>
    </Paper>
  );
};

const Suggestions = ({ responses }) => {
  return (
    <Paper
      elevation={5}
      sx={{ maxWidth: { xs: "100%", md: "45%" }, marginTop: "10px" }}
    >
      <List sx={{ paddingTop: "20px", paddingBottom: "30px" }}>
        {responses.map((resp) => (
          <>
            {resp}
            <Divider variant="middle" textAlign="center" />
          </>
        ))}
      </List>
    </Paper>
  );
};
const SearchBar = ({ filterHandler }) => {
  const [searchResponses, setSearchResponses] = useState([]);
  const [isFocused, setFocus] = useState(false);
  const searchRef = useRef(null);
  const [showSuggestions, setSuggestions] = useState(false);
  const [searchValue, setSearchValue] = useState("");

  const buildSuggestions = (eventValue) => {
    setSearchResponses(
      searchSuggestions
        .filter((suggestion) => {
          const lowerSuggestion = suggestion.toLowerCase();
          const val = eventValue.toLowerCase();
          return lowerSuggestion.indexOf(val) > -1;
        })
        .map((suggestion) => {
          const lowerSuggestion = suggestion.toLowerCase();
          const val = eventValue.toLowerCase();
          const ind = lowerSuggestion.indexOf(val);
          return (
            <ListItemButton
              sx={{
                paddingTop: "20px",
                paddingBottom: "10px",
                fontSize: "18px",
                fontWeight: "bold",
              }}
              onClick={(event) => {
                console.log("build suggestions item clicked", event);
                filterHandler(event.target.textContent);
              }}
            >
              {suggestion.substring(0, ind)}
              <mark style={{ backgroundColor: "#f7e7d0" }}>
                {suggestion.substring(ind, ind + val.length)}
              </mark>
              {suggestion.substring(ind + val.length, suggestion.length)}
            </ListItemButton>
          );
        })
    );
  };

  const handleOnChange = (event) => {
    const eventValue = event.target.value;
    console.log("current value is ", eventValue);
    if (eventValue !== "") {
      setSuggestions(false);
    } else {
      setSuggestions(true);
    }

    setSearchValue(eventValue);

    buildSuggestions(eventValue);
  };
  return (
    <Box
      sx={{
        marginTop: "-30px",
        width: "100%",
        marginBottom: "24px",
      }}
    >
      <Paper
        elevation={5}
        sx={{
          padding: "20px",
          display: "flex",
          justifyContent: "space-between",
          alignItems: "center",
        }}
      >
        <TextField
          variant="standard"
          sx={{
            color: "#2B3939",
          }}
          fullWidth
          onFocus={() => {
            setFocus(true);
            setSuggestions(true);
            if (searchValue !== "") buildSuggestions(searchValue);
          }}
          onBlur={() => {

//Here's my focus handler
            setTimeout(() => {
              setFocus(false);
              setSuggestions(false);
            }, 200);
            // setFocus(false);
            // setSuggestions(false);
          }}
          onChange={handleOnChange}
          inputRef={searchRef}
          InputProps={{
            disableUnderline: true,
            placeholder: "Search",
            style: {
              color: "black",
              fontWeight: "bold",
              fontSize: "18px",
            },
          }}
        />
        <Button
          variant="text"
          sx={{
            textTransform: "none",
            color: "#C5C5C5",
            fontWeight: "bold",
            fontSize: "14px",
          }}
          onClick={() => {
            const val = searchRef.current.value.toLowerCase();
            const index = searchSuggestions.findIndex((element) => {
              return element.toLowerCase() === val;
            });
            if (index > -1) filterHandler(searchSuggestions[index]);
            else filterHandler(searchRef.current.value);
          }}
        >
          Submit
        </Button>
      </Paper>
      {isFocused && showSuggestions && searchValue === "" && (
        <TopSuggestions
          filterHandler={filterHandler}
          
        />
      )}

      {isFocused && !showSuggestions && searchValue !== "" && (
        <Suggestions responses={searchResponses} />
      )}
    </Box>
  );
};

export default SearchBar;