添加设置状态更改会导致React中出现无限循环

问题描述 投票:0回答:2

[我正在尝试使用gatsby(反应)和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
    }
reactjs gatsby
2个回答
0
投票

[useEffect运行并设置posts时,您的条件将置为true。调用setPosts,导致重新渲染,调用setPosts,依此类推。您可以具有一个控制变量,以确保if statement仅断言一次true

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

    if (posts && !done) {
        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)
        setDone(true)
    }

0
投票

[除了少数用例之外,您不应在组件渲染方法中直接调用setState,如果这样做,则需要谨慎选择正确的条件。

通常,如果您的状态取决于提供给组件的道具,就会出现这种情况。基于类的组件生命周期方法称为getDerivedStateFromProps。您在这里不需要。

看来您正在尝试缩小API端点的结果。可以在调用setPosts

之前在fetch回调中完成转换。
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);
        })
}, [])
© www.soinside.com 2019 - 2024. All rights reserved.