我确实有一个 Spinner 在应用程序中工作,但我认为它的实现不太正确。
加载/重新加载页面时,微调器确实会显示。我使用了一些我发现的搜索示例,但我发现奇怪的是我必须在“setTimeout”中设置 isDataLoading=true ,然后设置 isDataLoading=false ,这与示例相反。
搜索速度很快,因为我使用的只是本地数据,而不是使用 Fetch 来获取数据。我遇到的问题是我认为旋转器应该在单击“员工”按钮时显示,因为它正在提取所有数据。事实并非如此,所以我认为 Spinner 没有正确实现。
解决方案:加载/重新加载数据时或单击“员工”按钮时显示微调器以显示所有员工。如果搜索部分名称,那么我相信该页面足够快,旋转器不需要显示,但如果需要的话可以显示。
SearchText - 用于搜索员工的输入字段。员工按钮显示所有员工。
搜索结果 - 显示搜索结果或所有员工。
数据(2K中3条测试记录)
const data = [{
"ROW_NUMBER": 1,
"PIDM": 991,
"NAME": "Elvis Presley",
"PHONE": "999-999-9999",
"EMAIL": "<a href=mailto:[email protected]>test<\u002fa>",
"CAMPUS": "Main 1",
"DEPARTMENT": "Eng /Read /Frgn Lang/ IDS / Comm.",
"JOBTITLE": null,
"SEARCHTYPE": null,
"SEARCHHEADER": null
}, {
"ROW_NUMBER": 2,
"PIDM": 992,
"NAME": "James Dean",
"PHONE": "999-999-9999",
"EMAIL": "<a href=mailto:[email protected]>test<\u002fa>",
"CAMPUS": "Main 2",
"DEPARTMENT": "Instructional Resources",
"JOBTITLE": "Lead Librarian-Systems",
"SEARCHTYPE": null,
"SEARCHHEADER": null
}, {
"ROW_NUMBER": 3,
"PIDM": 993,
"NAME": "Marilyn Monroe",
"PHONE": "999-999-9999",
"EMAIL": "<a href=mailto:[email protected]>test<\u002fa>",
"CAMPUS": "Main 3",
"DEPARTMENT": "Housekeeping",
"JOBTITLE": "Custodian",
"SEARCHTYPE": null,
"SEARCHHEADER": null
}];
搜索文本(用于搜索的输入字段和用于加载所有员工的员工按钮)
import { useState } from 'react';
import { faMagnifyingGlass, faPeopleGroup, faBuildingUser, faArrowsRotate } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import utilStyles from '../styles/utils.module.css';
const SearchText = ({ cards, setSearchResults }) => {
const [enteredText, setEnteredText] = useState("")
const onFormSubmit = (event) => {
event.preventDefault();
}
const onChange = (event) => {
const fields = ['NAME', 'CAMPUS', 'DEPARTMENT', 'JOBTITLE'];
const query = event.target.value.toLowerCase();
//if (!event.target.value) setSearchResults(cards);
(event.target.value) || setSearchResults(cards);
const filterData = (cards, fields, query) => {
return cards.filter(record => fields.some(field => record[field]?.toLowerCase().includes(query)));
};
setEnteredText(event.target.value);
setSearchResults(filterData(cards, fields, query));
}
const onEmployees = (event) => {
setEnteredText("");
setSearchResults(cards);
}
const onReset = (event) => {
setEnteredText("");
setSearchResults(cards);
}
return (
<>
<form id='EmployeeSearchText' onSubmit={onFormSubmit}>
<div className="container-fluid p-3">
<div id='Row1' className={`row ${utilStyles.divPadding}`}>
<div id='Row1Column1' className="col">
<div id='SearchText-container' className={utilStyles.searchBar}>
<FontAwesomeIcon icon={faMagnifyingGlass} className={utilStyles.icon} />
<input id='SearchText' type="text" name="SearchText" placeholder="Search Last Name; First Name; Campus; Deparment....." value={enteredText} onChange={onChange} className={`form-control ${utilStyles.inputField} ${utilStyles.inputPadding}`} />
</div>
</div>
</div>
<div className='text-center'>
<div id='Row2' className={`row ${utilStyles.divPadding}`}>
<div id='Row2Column1' className="col">
<div id='Employees-container'>
<button id='EmployeeListing' type="button" onClick={onEmployees} className={utilStyles.btnYellow}>Employees <FontAwesomeIcon icon={faPeopleGroup} /></button>
</div>
</div>
<div id='Row2Column2' className="col">
<div id='DepartmentListing-container'>
<button id='DepartmentListing' type="button" className={utilStyles.btnYellow}>Department Listing <FontAwesomeIcon icon={faBuildingUser} /></button>
</div>
</div>
<div id='Row2Column3' className="col">
<div id='SearchTextReset-container'>
<button id='SearchTextReset' type="button" onClick={onReset} className={utilStyles.btnGrey}>Reset <FontAwesomeIcon icon={faArrowsRotate} /></button>
</div>
</div>
</div>
</div>
</div>
</form>
</>
)
}
export default SearchText;
搜索结果(显示搜索结果或显示所有员工)
import { useState } from 'react';
import { RotatingLines } from "react-loader-spinner";
import parse from 'html-react-parser';
import { faPhone, faEnvelope } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import utilStyles from '../styles/utils.module.css';
const SearchResults = ({ searchResults }) => {
const [isDataLoading, setIsDataLoading] = useState(true);
setTimeout(() => {
setIsDataLoading(false);
}, 2);
const Loader = () => {
return (
<RotatingLines
strokeColor="#51abff"
strokeWidth="5"
animationDuration="0.75"
width="100"
visible={true}
/>
)
}
const emp = searchResults.map(employee =>
<div className="col col-12 col-sm-6 col-xl-4 mb-4">
<div className="col-12 mb-4">
<div className={`card ${utilStyles.cardBody}`}>
<div className="card-body">
<div className={`${utilStyles.ribbonLight} ${utilStyles.ribbonBottomRight}`}><span>{employee.CAMPUS}</span></div>
<h3 className="card-title card-name">{employee.NAME}</h3>
<h6 className={`${utilStyles.cardJobtitle} mb-2`}>{employee.JOBTITLE}</h6>
<p className={`${utilStyles.cardText} ${utilStyles.cardDepartment}`}>{employee.DEPARTMENT}</p>
<div>
<p className={utilStyles.cardTextBottom}><FontAwesomeIcon icon={faPhone} className={utilStyles.cardTextIcons} /><span className={utilStyles.cardPhoneEmail}>W:</span>{employee.PHONE}</p>
<p className={utilStyles.cardTextBottom}><FontAwesomeIcon icon={faEnvelope} className={utilStyles.cardTextIcons} /><span className={utilStyles.cardPhoneEmail}>W:</span>{parse(employee.EMAIL)}</p>
</div>
</div>
</div>
</div>
</div>
);
const content = emp?.length ? emp : <article><p className={`${utilStyles.cardResultCount}`}>No Matching Results</p></article>
return (
<div className="container">
<div className="row">{isDataLoading ? (<div style={{width: "100px", margin: "auto"}}><Loader /></div>) : content}</div>
</div>
);
}
export default SearchResults;
好的,我能够修复我的代码并使旋转器正常工作。
我做了什么?
解决方案:
我转而使用react-bootstrap 中的“Spinner”。添加了“const [isLoading, setIsLoading] = useState(true);”到应用程序页面并将其传递下来。
代码现在可以正常工作,在显示结果之前显示“旋转器”。
应用程序
import { useState } from 'react';
import { employees } from './search-data/data.js';
import SearchHeader from './search-header/page.js';
import SearchText from './search-text/page.js';
import SearchResults from './search-results/page.js';
function App() {
const [cards, setCards] = useState(employees);
const [searchResults, setSearchResults] = useState(employees);
const [isLoading, setIsLoading] = useState(true);
return (
<>
<SearchHeader />
<SearchText cards={cards} setIsLoading={setIsLoading} setSearchResults={setSearchResults} />
<SearchResults setIsLoading={setIsLoading} isLoading={isLoading} searchResults={searchResults} />
</>
);
}
export default App;
搜索结果
import { useEffect } from 'react';
import { Spinner } from "react-bootstrap";
import Card from 'react-bootstrap/Card';
import parse from 'html-react-parser';
import { faPhone, faEnvelope } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import utilStyles from '../styles/utils.module.css';
const SearchResults = ({ setIsLoading, isLoading, searchResults }) => {
var employees;
useEffect(() => {
setTimeout(() => {
setIsLoading(false);
}, 100);
});
{(searchResults?.length !== 0) &&
(employees = searchResults.map(employee =>
<Card className={`col col-12 col-sm-6 col-xl-4 mb-4 ${utilStyles.cards}`} style={{ width: '25rem' }}>
<Card.Body>
<Card.Title className={`${utilStyles.ribbon} ${utilStyles.ribbonLight} ${utilStyles.ribbonBottomRight}`}><span>{employee.CAMPUS}</span></Card.Title>
<Card.Title as="h3" className="card-title card-name">{employee.NAME}</Card.Title>
<Card.Title as="h6" className={`${utilStyles.cardJobtitle} mb-2`}>{employee.JOBTITLE?.length ? employee.JOBTITLE : <br />}</Card.Title>
<Card.Title className={`${utilStyles.cardText} ${utilStyles.cardDepartment}`}>{employee.DEPARTMENT}</Card.Title>
<Card.Title className={`${utilStyles.cardText} ${utilStyles.cardTextBottom}`}><FontAwesomeIcon icon={faPhone} className={utilStyles.cardTextIcons} /><span className={utilStyles.cardPhoneEmail}>W:</span>{employee.PHONE}</Card.Title>
<Card.Title className={`${utilStyles.cardText} ${utilStyles.cardTextBottom}`}><FontAwesomeIcon icon={faEnvelope} className={utilStyles.cardTextIcons} /><span className={utilStyles.cardPhoneEmail}>W:</span>{parse(employee.EMAIL)}</Card.Title>
</Card.Body>
</Card>
))
};
return (
<div className="container">
<div className="row">
{!isLoading && (employees?.length ? employees : <article><p className={`${utilStyles.cardResults}`}>No Matching Results</p></article>)}
{isLoading && (<div style={{width: "100px", margin: "auto"}}><Spinner as="span" variant="secondary" aria-hidden="true" animation="border" style={{ width: "4rem", height: "4rem" }}/></div>)}
</div>
</div>
);
}
export default SearchResults;
这些变化似乎解决了我的问题。