【问题标题】:I have a search function that only works after typing the second letter我有一个搜索功能,只有在输入第二个字母后才有效
【发布时间】:2021-03-26 07:58:01
【问题描述】:

所以我有一个基本的信使反应应用程序。

但我的搜索功能只有在我输入第二个字母后才起作用。怎么回事?我猜它必须与我的 onChange 处理程序或 e.target.value 做些什么?

此外,当我退格时,我的 setSearch 钩子不会清除为空的“”。

输入第一个字母“f”

输入第二个字母“u”

代码

import { Avatar, IconButton } from '@material-ui/core';
import React, { useEffect, useState } from 'react';
import './Sidebar.css';
import SearchIcon from '@material-ui/icons/Search';
import { RateReviewOutlined } from '@material-ui/icons';
import { SidebarChat } from './SidebarChat';
import { useSelector } from 'react-redux';
import { selectUser } from './features/userSlice';
import db, { auth } from './firebase';

import { makeStyles } from '@material-ui/core/styles';
import Modal from '@material-ui/core/Modal';
import Backdrop from '@material-ui/core/Backdrop';
import Fade from '@material-ui/core/Fade';

const useStyles = makeStyles((theme) => ({
  modal: {
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
  },
  paper: {
    backgroundColor: theme.palette.background.paper,
    border: '2px solid #000',
    boxShadow: theme.shadows[5],
    padding: theme.spacing(2, 4, 3),
  },
}));

export function Sidebar(props) {
  const user = useSelector(selectUser);
  const [chats, setChats] = useState([]);
  const classes = useStyles();
  const [open, setOpen] = useState(false);
  const [search, setSearch] = useState('');

  const handleOpen = () => {
    setOpen(true);
  };

  const handleClose = () => {
    setOpen(false);
  };

  useEffect(() => {
    db.collection('chats').onSnapshot((snapshot) =>
      setChats(
        snapshot.docs.map((doc) => ({
          id: doc.id,
          data: doc.data(),
        }))
      )
    );
  }, []);

  const addChat = () => {
    const chatName = prompt('Please enter a chat name');
    if (chatName) {
      db.collection('chats').add({
        chatName: chatName,
      });
    }
  };

  const searchFunction = (e) => {
    setSearch(e);
    console.log(search);
    console.log(chats);
    const filtered = chats.filter((chat) => {
      return chat.data.chatName.toLowerCase().includes(search.toLowerCase());
    });
    // console.log(filtered)
    setChats(filtered);
  };
  return (
    <div className="sidebar">
      <div className="sidebar__header">
        <Avatar
          onClick={handleOpen}
          src={user.photo}
          className="sidebar__avatar"
        />
        <div className="sidebar__input">
          <SearchIcon />
          <input
            placeholder="Search"
            value={search}
            onChange={(e) => searchFunction(e.target.value)}
          />
        </div>
        <IconButton variant="outlined" className="sidebar__inputButton">
          <RateReviewOutlined onClick={addChat} />
        </IconButton>
      </div>
      <div className="sidebar__chats">
        {chats.map(({ id, data: { chatName } }) => (
          <SidebarChat key={id} id={id} chatName={chatName} />
        ))}
      </div>

      <Modal
        aria-labelledby="transition-modal-title"
        aria-describedby="transition-modal-description"
        className={classes.modal}
        open={open}
        onClose={handleClose}
        closeAfterTransition
        BackdropComponent={Backdrop}
        BackdropProps={{
          timeout: 500,
        }}
      >
        <Fade in={open}>
          <div className={classes.paper}>
            <h2 id="transition-modal-title">
              Are you sure you want to sign out?
            </h2>
            <button onClick={() => auth.signOut()}>Yes</button>
            <button onClick={handleClose}>No</button>
          </div>
        </Fade>
      </Modal>
    </div>
  );
}

【问题讨论】:

  • @fortunee 感谢您的编辑!哇,我有很多要解决的!你使用了某种 eslint 吗?
  • 太棒了!我也刚刚给你发了一个答案

标签: reactjs react-hooks


【解决方案1】:

在 searchFunction 中,您正在根据搜索值的当前状态更新聊天,而不是您要设置的状态。您应该根据您的 searchFunction e 中的参数过滤您的聊天记录。

为了进一步澄清,即使您在调用setChats(filtered) 之前调用setSearch(e),这两个状态更新也会同时发生。因此search 的状态值尚未更新为新值。

【讨论】:

  • 知道了,我基本上使用的是以前的状态,而不是使用 E
【解决方案2】:

setSearch 默认情况下是异步的,这意味着您可以在设置值后立即获取它们。

使用search 执行过滤器很可能会使用search 的先前值

为防止这种情况发生,您可以像这样在过滤器中使用 e 参数传递给 searchFunction

return chat.data.chatName.toLowerCase().includes(e.toLowerCase());

【讨论】:

  • 明白了!这是有道理的。本质上是使用搜索而不是 E,我使用的是检索以前的状态
  • React 状态钩子不接受多个参数。
  • 很好@StephanOlsen,状态钩子确实不允许,它只在类组件中可用。谢谢你。
猜你喜欢
  • 2012-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-11
  • 1970-01-01
  • 2015-11-13
  • 2022-11-15
  • 1970-01-01
相关资源
最近更新 更多