通过关键字更改进行搜索时,使用自定义的React挂钩来优化API数据的获取

时间:2020-06-19 11:27:17

标签: javascript reactjs material-ui react-hooks

我是React Hooks的新手。我编写了一个小代码,向用户显示课程列表。它包含2个主要组件CourseListCourse和一个自定义钩子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

1 个答案:

答案 0 :(得分:0)

您可以进行2种更改以获得更好的ui体验

  • 取消对搜索的API调用
  • 请勿在useEffect清除中将状态设置为空

您可以选择编写自己的自定义防抖动功能,也可以从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>
  );
}

Edit FORM VALUES

相关问题