我正在编写一些使用反应钩子形式来捕获输入状态的代码,但我不确定为什么当我输入输入时,特别是占位符文本为“或按名称搜索联系人类型...”的代码,我没有看到输入框填充任何字符,我基本上输入它,它保持空白。我尝试过 console.log(watch("searchValue")) 但我只是在控制台中出现空格。知道这是怎么回事吗?看来表单输入中的寄存器函数实际上并没有捕获值
/* eslint-disable react-hooks/exhaustive-deps */
export default function Home() {
const ref = useRef<HTMLDivElement>(null);
const user = useAuthUser();
const depts = useDepts();
const [currentTab, setCurrentTab] = useState("My Contacts");
const [isAllDepts, setIsAllDepts] = useState(false);
const [selectedSchoolId, setSelectedSchoolId] = useState(user.DeptId);
const [selectedContactType, setSelectedContactType] = useState<ContactType | null>();
const [showModalEmplSearch, setShowModalEmplSearch] = useState(false);
const [showModalEditContact, setShowModalEditContact] = useState(false);
const [showModalExempt, setShowModalExempt] = useState(false);
const [selectedContact, setSelectedContact] = useState(initContact);
const syncContacts = useSyncContacts(selectedSchoolId);
const contactTypes = useContactTypesAppliesTo(selectedSchoolId);
const allContactTypes = useContactTypes();
const contacts = useContactsByDeptType(selectedSchoolId, selectedContactType?.PkId ?? 0);
const allContactsFromAllTypes = useContactsByDept(selectedSchoolId);
const contactsByType = useContactsbyType(selectedContactType?.PkId ?? 0);
const upsertContact = useUpsertContact();
const deleteContact = useDeleteContact();
const deleteExemption = useDeleteExemption();
const { register, watch, reset, setValue } = useForm();
console.log(watch("searchValue"));
const [isHoveredContacts, setIsHoveredContacts] = useState(false);
const [isHoveredRequested, setIsHoveredRequested] = useState(false);
const [isHoveredLookup, setIsHoveredLookup] = useState(false);
const [isHoveredGlobal, setIsHoveredGlobal] = useState(false);
const [tab, setTab] = useState("");
const handleIconMouseEnter = (e: any) => {
const tabName = e.target.parentElement.innerText.trim(); // Get the tab name from the parent element
if (tabName === "My Contacts") {
setIsHoveredContacts(true);
setTab(tabName);
} else if (tabName === "Requested Contacts") {
setIsHoveredRequested(true);
setTab(tabName);
} else if (tabName === "Contact Lookup") {
setIsHoveredLookup(true);
setTab(tabName);
} else if (tabName === "Global Search") {
setIsHoveredGlobal(true);
setTab(tabName);
setSelectedSchoolId(selectedSchoolId ?? user.DeptId);
}
};
const handleMouseLeave = (tabName: string) => {
if (tabName === "My Contacts") {
setIsHoveredContacts(false);
} else if (tabName === "Requested Contacts") {
setIsHoveredRequested(false);
} else if (tabName === "Contact Lookup") {
setIsHoveredLookup(false);
} else if (tabName === "Global Search") {
setIsHoveredGlobal(false);
}
};
useEffect(() => {
if (currentTab === "lookup") {
setIsAllDepts(true);
setSelectedContactType(null);
setSelectedSchoolId(selectedSchoolId ?? user.DeptId);
setValue("hasIssues", false);
} else if (currentTab === "Requested contacts") {
setSelectedContactType(null);
setSelectedSchoolId(selectedSchoolId ?? user.DeptId);
setValue("hasIssues", false);
setIsAllDepts(false);
} else if (currentTab === "My Contacts") {
setSelectedContactType(null);
setSelectedSchoolId(selectedSchoolId ?? user.DeptId);
setValue("hasIssues", false);
setIsAllDepts(false);
contactTypes.refetch();
} else if (currentTab === "Global Search") {
setIsAllDepts(true);
setSelectedContactType(null);
setSelectedSchoolId(selectedSchoolId ?? user.DeptId);
setValue("hasIssues", false);
}
}, [currentTab]);
// When a user first logs in, run the sync service to make sure the dept is in sync
useEffect(() => {
sync();
}, []);
// If the URL has "/issues" on first page load,
// then automatically check the box to show contact types with issues
useEffect(() => {
if (window.location.pathname.includes("issues")) {
setValue("hasIssues", true);
}
}, []);
// Every time an impersonation happens, just reset the selectedSchoolId
useEffect(() => setSelectedSchoolId(user.DeptId), [user]);
/** Call the sync service to sync the contacts with the DB */
const sync = async () => {
await syncContacts.refetch();
await contactTypes.refetch();
};
/** Handles what happens when the "View all departments" checkbox is enabled/disabled */
const handleIsAllDeptsCheckBox = () => {
setIsAllDepts(!isAllDepts);
setSelectedContactType(null);
setSelectedSchoolId(user.DeptId);
setValue("hasIssues", false);
};
const deptsRequesting = [
...new Set(
(isAllDepts ? allContactTypes.data : contactTypes.data)?.map((ct) => ct.Department.DeptName),
),
].sort((a, b) => (a > b ? 1 : -1));
const filteredContactTypes = (isAllDepts ? allContactTypes.data : contactTypes.data)?.filter(
(ct) => (watch("selectedDepts") ?? []).includes(ct.Department.DeptName),
);
/** Checks if the array of issues from a contact type includes one of the `statusIssues` elements */
const checkIfStatusIssue = (issues: ContactStatus[]) => {
for (const i of issues) if (statusIssues.includes(i)) return true;
};
const getContactTypes = () =>
(!watch("selectedDepts") || watch("selectedDepts").length === 0
? (isAllDepts ? allContactTypes.data : contactTypes.data) ?? []
: filteredContactTypes
)?.filter((ct) => ct.Title.toLowerCase().includes((watch("searchValue") ?? "").toLowerCase()));
const getAllContacts = () =>
(watch("searchValue").length === 0
? allContactsFromAllTypes.data
: allContactsFromAllTypes?.data?.filter((x) =>
x.ContactType.Title.toLowerCase().includes((watch("searchValue") ?? "").toLowerCase()),
)) ?? [];
const getDepts = () =>
(watch("searchValue").length === 0
? allContactsFromAllTypes.data
: allContactsFromAllTypes?.data?.filter((x) =>
x.ContactType.Title.toLowerCase().includes((watch("searchValue") ?? "").toLowerCase()),
)) ?? [];
// const getAllContacts = () =>
// watch("searchValue") === ""
// ? allContactsFromAllTypes?.data ?? []
// : allContactsFromAllTypes?.data?.filter((ct) =>
// ct.ContactEmployee.JobTitle.toLowerCase().includes(
// (watch("searchValue") ?? "").toLowerCase(),
// ),
// ) ?? [];
const handleRemoveExemption = async () => {
const path = `${Methods.Exemptions}/${selectedContactType?.PkId}/${selectedSchoolId}`;
const exemption = await queryClient.fetchQuery<Exemption>("exemption", () => API.Get(path));
await deleteExemption.mutateAsync(exemption.PkExemptionId ?? "");
await toast.promise(sync(), {
loading: "Removing exemption...",
success: `Successfully removed the exemption for ${selectedContactType?.Title}!`,
error: "Could not remove the exemption.",
});
const updatedCt = await queryClient.fetchQuery<ContactType[]>([
`${Methods.ContactTypesAppliesToDept}/${selectedSchoolId}`,
]);
setSelectedContactType(updatedCt.find((ct) => ct.PkId === selectedContactType?.PkId));
};
const handleAddContact = async (emp: Employee) => {
setShowModalEmplSearch(false);
const postData: ContactPostModel = {
ContactTypeId: selectedContactType?.PkId ?? 0,
DeptId: selectedSchoolId,
ContactEmplId: emp.EmplId,
ContactStatus: ContactStatus.Ok,
};
if (selectedContact.PkId) postData.PkId = selectedContact.PkId;
await upsertContact.mutateAsync(postData);
setSelectedContact(initContact);
contacts.refetch();
contactTypes.refetch();
toast.success(
`Successfully added ${emp.FirstName} ${emp.LastName} as a new contact for "${selectedContactType?.Title}"`,
);
};
const handleDeleteContact = async (c: Contact) => {
await deleteContact.mutateAsync(c.PkId ?? "");
contacts.refetch();
await toast.promise(sync(), {
loading: "Deleting contact...",
success: `Successfully removed ${c.ContactEmployee.FirstName} ${c.ContactEmployee.LastName} as a contact for ${selectedContactType?.Title}`,
error: "Could not delete this contact.",
});
};
function handleClick(e: any) {
setCurrentTab(e);
//result will be the eventKey of the tab you clicked on.
// `homeTab` (when clicked on home tab)
// `profileTab` (when clicked on profile tab)
// `constactTab` (when clicked on Contact tab)
}
const contactsTooltip = (
<Tooltip id="contacts-tooltip">Manage contacts for your school or department</Tooltip>
);
const requestedContactsTooltip = (
<Tooltip id="requested-contacts-tooltip">
Manage the contact types that are related to your department
</Tooltip>
);
const contactLookupTooltip = (
<Tooltip id="contact-lookup-tooltip">Lookup and export contacts</Tooltip>
);
return (
<div>
<Helmet>
<title>Points of Contact</title>
</Helmet>
<p>
<span style={{ fontWeight: "bold", fontSize: "2rem" }}>
{selectedSchoolId &&
`Viewing ${
isAllDepts
? "All Departments"
: getDeptName(depts.data, selectedSchoolId, user.Department)
}`}
</span>
</p>
<hr />
<ExportContacts
contacts={allContactsFromAllTypes.data ?? []}
title={getDeptName(depts.data, selectedSchoolId, user.Department)}
isEntireList
/>
<br />
<Tabs
defaultActiveKey="profile"
id="justify-tab-example"
className="mb-3"
style={{ marginTop: "20px" }}
onSelect={(e) => handleClick(e)}
activeKey={currentTab}
>
<Tab
eventKey="My Contacts"
title={
<span style={{ position: "relative", display: "inline-block" }}>
My Contacts
<OverlayTrigger placement="top" overlay={contactsTooltip} show={isHoveredContacts}>
<i
className="fa-solid fa-circle-info"
style={{ marginLeft: "10px", color: "#3870c9" }}
onMouseEnter={handleIconMouseEnter}
onMouseLeave={() => handleMouseLeave(tab)}
/>
</OverlayTrigger>
</span>
}
>
<Row style={{ backgroundColor: "#F5F5F5", padding: 20, borderRadius: 10 }}>
<Col md={4}>
<div>
<h3>My Contacts</h3>
<div id="contact-type-filter" style={{ marginBottom: "0.5rem" }}>
<i style={{ color: "#727272" }}>Manage contacts for your school or department.</i>{" "}
<Dropdown
autoClose="outside"
style={{
cursor: "pointer",
}}
>
<Dropdown.Toggle
id="filter-text"
as="span"
style={{
paddingLeft: 8,
paddingRight: 8,
}}
title="More options"
>
<i className="fa-solid fa-filter p-1" />
Dept Filter
</Dropdown.Toggle>
<Dropdown.Menu>
<label style={{ padding: "2px 14px", textAlign: "center" }}>
Filter by the department(s) requesting these contact types
</label>
<Button
variant="outline-primary"
style={{
display: "flex",
justifyContent: "center",
padding: "6px 0px",
width: "80%",
margin: "0 auto",
}}
onClick={() => reset()}
>
Reset Filters
</Button>
<Dropdown.Divider />
<Form.Group
style={{
padding: "2px 14px",
width: 350,
maxHeight: "25rem",
overflowY: "scroll",
}}
>
{deptsRequesting.map((dept) => (
<Form.Check
key={dept}
label={dept}
value={dept}
{...register("selectedDepts")}
/>
))}
</Form.Group>
</Dropdown.Menu>
</Dropdown>
</div>
{!isAllDepts && (
<Form.Check
style={{ paddingLeft: "2.2rem" }}
label="Show Contact Types With Issues"
{...register("hasIssues")}
/>
)}
<Form>
<Form.Control
placeholder="Or search for a contact type by name..."
{...register("searchValue")}
/>
</Form>
<ListGroup
style={{
borderColor: "#BCBCBC",
height: "30rem",
overflow: "auto",
border: "1px solid #bcbcbc7d",
background: "white",
marginTop: "0.5rem",
}}
>
{contactTypes.isLoading || allContactTypes.isLoading ? (
<ContactTypesLoading />
) : (
(watch("hasIssues")
? getContactTypes()?.filter(
(ct) =>
(ct.HasIssues && !ct.Issues.includes(ContactStatus.Exempted)) ||
(ct.Issues.includes(ContactStatus.Exempted) && ct.MinQty > 0),
)
: getContactTypes()
)?.map((ct) => (
<ListGroup.Item
key={ct.PkId}
onClick={() => {
setSelectedContactType(ct);
ref.current?.scrollIntoView({ behavior: "smooth" });
}}
active={selectedContactType?.PkId === ct.PkId}
style={{ border: "none" }}
action
>
<i
className={`fa-solid fa-circle-${
ct.HasIssues && checkIfStatusIssue(ct.Issues) ? "exclamation" : "check"
}`}
style={{
color: `${
selectedContactType === ct
? "white"
: ct.HasIssues && checkIfStatusIssue(ct.Issues)
? "#8f0a15"
: "green"
}`,
paddingRight: 6,
}}
title={
(ct.Issues ?? []).length > 0
? Object.values(ContactStatusDescr).find(
(c, i) =>
i === ct.Issues[0] && ct.Issues[0] !== ContactStatus.Exempted,
)
: ""
}
/>
<b>{ct.Title}</b>
<br />
<span style={{ fontSize: "0.8rem" }}>
Requested By: {ct.Department.DeptName}
</span>
<br />
{!isAllDepts && (
<span style={{ fontSize: "0.8rem" }}>
Required # of Contacts: {ct.MinQty}
</span>
)}
{(ct.Issues ?? [])?.at(0) === ContactStatus.Exempted && (
<Badge bg="warning" style={{ float: "right" }}>
Exempt
</Badge>
)}
</ListGroup.Item>
))
)}
</ListGroup>
</div>
</Col>
问题可能在于您使用的组件不接受注册属性,请尝试使用默认的 html 标签:
< input type="text" placeholder="Enter search value" {...register("searchValue")} />
希望它有效。