我是React Hooks的新手。我编写了一个小代码,向用户显示课程列表。它包含2个主要组件CourseList
和Course
和一个自定义钩子useCourseList
。这是自定义钩子的代码:
function useCourseList(searchString) {
const [courses, setCourses] = useState([]);
useEffect(() => {
function handleCourseListUpdating(nextCourses) {
setCourses(nextCourses);
}
getCourses(searchString, handleCourseListUpdating)
return () => {
setCourses([]);
}
}, [searchString]);
return courses;
}
上面的代码是通过getCourses
函数通过搜索字符串获取api数据。然后,它将检索到的数据更新为courses
组件呈现的CourseList
状态。 useEffect
函数以searchString
为依存关系触发,一旦搜索字符串发生变化,就可以继续更新课程数据。
尽管与这些关键字更改有关的数据结果相同,但Web浏览器会刷新多次,与搜索字符串的每个字符更改相对应。 例如,我们正在寻找带有关键字“ Game”的游戏课程。然后在useE上调用4次,分别与“ G”,“ Ga”,“ Gam”和“ Game”一起生效。这些关键字与我当前的api数据给出的结果相同,但是它们通过Web界面不断更新React DOM。 这会导致浏览器闪烁4次,这是不必要的。这也会给用户带来糟糕的体验。
有什么解决方案可以防止由于数据仍然一致而导致更新UI?数据流有问题吗?
为进行演示,您可以在此处查看完整的示例代码: CodeSandbox
答案 0 :(得分:0)
您可以进行2种更改以获得更好的ui体验
您可以选择编写自己的自定义防抖动功能,也可以从lodash或下划线之类的库中使用它。完成后,您可以使用useMemo
创建一个getCourses函数的去抖动实例,并在useEffect内部调用它
const debounce = (fn, delay) => {
let timer = null;
return function(...args) {
if (timer){
clearInterval(timer);
}
timer = setTimeout(() => {
fn.apply(this, args);
}, delay)
}
}
// A custom Hook
function useCourseList(searchString) {
const [courses, setCourses] = useState([]);
const getDebouncedCourses = useMemo(() => debounce(getCourses, 300), []);
useEffect(() => {
function handleCourseListUpdating(courses) {
setCourses(courses);
}
getDebouncedCourses(searchString, handleCourseListUpdating);
}, [searchString, getDebouncedCourses]);
return courses;
}
// CourseList component
function CourseList() {
const [searchString, setSearchString] = useState('');
const courses = useCourseList(searchString)
return (
<div>
{courses ? (
<div>
<TextField style={{ padding: 24 }}
id="searchInput"
placeholder="Search for Courses"
margin="normal"
onChange={event => setSearchString(event.target.value)}
/>
<Grid container spacing={4} style={{ padding: 24 }}>
{courses.map((course, index) => (
<Grid key={index} item xs={12} sm={6} lg={4} xl={3}>
<Course course={course} />
</Grid>
))}
</Grid>
</div>
) : "No courses found"}
</div>
);
}