1

我正在尝试使用 gatsby (react) 和 Fuse.js 创建离线模糊搜索,但我遇到了使用 setState 存储“搜索”字词的问题。

我收到以下错误:重新渲染太多。React 限制了渲染的数量以防止无限循环。

我不确定如何保存新状态(下面的代码)

 const [posts, setPosts] = useState(null)
    useEffect(() => {
        fetch("/index.json")
            .then(response => response.json())
            .then(function(data) {
                setPosts(data.data.allContentfulPost.edges)
            })
    }, [])

    if (posts) {
        var list = posts //returns 326 items
        var options = {
            shouldSort: true,
            threshold: 0.6,
            location: 0,
            distance: 100,
            maxPatternLength: 32,
            minMatchCharLength: 1,
            keys: ["node.title", "node.meta"],
        }
        var fuse = new Fuse(list, options)
        var results = fuse.search("marketing") //returns 11 items
        setPosts(results) //causes infinite loop
    }
4

2 回答 2

1

解决此问题的一种方法是对过滤后的帖子使用另一种状态。并保留原始帖子以备将来使用:

const [posts, setPosts] = useState([]);
const [filteredPosts, setFilteredPosts] = useState([]);

useEffect(() => {
    fetch("/index.json")
        .then(response => response.json())
        .then(function(data) {
            setPosts(data.data.allContentfulPost.edges)
        })
}, []);

useEffect(() => {
  var options = {
      shouldSort: true,
      threshold: 0.6,
      location: 0,
      distance: 100,
      maxPatternLength: 32,
      minMatchCharLength: 1,
      keys: ["node.title", "node.meta"],
  }
  var fuse = new Fuse(posts, options)
  var results = fuse.search("marketing") //returns 11 items
  setFilteredPosts(results) 
}, [posts])
于 2019-09-26T14:15:14.313 回答
0

除了极少数用例,您不应setState直接在组件的渲染方法中调用,如果这样做,您需要小心选择正确的条件来执行此操作。

如果您的状态取决于提供给组件的道具,通常就是这种情况。调用基于类的组件生命周期方法getDerivedStateFromProps。你在这里不需要那个。

看起来您正在尝试缩小 API 端点的结果。转换可以在调用之前在 fetch 回调中完成setPosts

useEffect(() => {
    fetch("/index.json")
        .then(response => response.json())
        .then(function(data) {
            const allPosts = data.data.allContentfulPost.edges;
            const options = {
                shouldSort: true,
                threshold: 0.6,
                location: 0,
                distance: 100,
                maxPatternLength: 32,
                minMatchCharLength: 1,
                keys: ["node.title", "node.meta"],
            }
            const fuse = new Fuse(allPosts, options)
            const found = fuse.search("marketing")

            setPosts(found);
        })
}, [])
于 2019-09-26T13:26:59.293 回答