【问题标题】:useEffect never stops runninguseEffect 永远不会停止运行
【发布时间】:2020-07-11 15:37:32
【问题描述】:

我相信这个问题已经被问过一百万次了。我看过至少 50% 的回复。但没有一个对我有用。

我有这个组件:

import React, { useState } from 'react';
import './App.css';
import { FormPaper, FormWrapper } from "teton-frontend-components/dist";
import { TextField } from '@material-ui/core';
import Network from "./Network";
import { TetonButton } from "teton-frontend-components";
import useDeepCompareEffect from "./deepCompare";

const logo = require("./timer.png");

function App() {
    const [ids, setIds] = useState([]);
    const [word, setWord] = useState("");
    const [loading, setLoading] = useState(false);
    const [id, setId] = useState("");

    useDeepCompareEffect(() => {
        Network.getWordIds().then(ids => {
            setIds(ids.data.data);
        });
    }, []);

    useDeepCompareEffect(() => {
        const id = window.location.href.split("/")[window.location.href.split("/").length - 1];
        if (id) {
            getWordWithId(id);
        }
    }, [])

    const getWord = () => {
        setLoading(true);
        const id = ids[Math.floor(Math.random() * ids.length)]._id;
        Network.getWordById(id).then(word => {
            const href = window.location.href;
            window.location.href = href.split("/")[0] + id;
            setWord(word.data.data);
        }).catch(err => {
            console.error(err);
        }).finally(() => {
            setLoading(false);
        });
    };

    const getWordWithId = id => {
        Network.getWordById(id).then(word => {
            const href = window.location.href;
            window.location.href = href.split("/")[0] + id;
            setWord(word.data.data);
        }).catch(err => {
            console.error(err);
        }).finally(() => {
            setLoading(false);
        });
    };

    return (
        <div className="App">
            <FormPaper width={"30%"} margin={"5% auto"} logo={logo} children={
                <div>
                    <FormWrapper children={
                        <div>
                            <p>Encavis Zusammenhalt Tabu</p>
                            <br/>
                            Wort
                            <br/>
                            <TextField color={"primary"} disabled={true} variant={"outlined"}
                                       style={{margin: "0 0 2% 0"}} value={word.word}/>
                            <br/>
                            Verbotene Wörter
                            <br/>
                            <TextField color={"primary"} disabled={true} variant={"outlined"}
                                       value={word.taboos ? word.taboos[0] : ""}/>
                            <br/>
                            <TextField color={"primary"} disabled={true} variant={"outlined"}
                                       value={word.taboos ? word.taboos[1] : ""}/>
                            <br/>
                            <TextField color={"primary"} disabled={true} variant={"outlined"}
                                       value={word.taboos ? word.taboos[2] : ""}/>
                            <br/>
                            <TextField color={"primary"} disabled={true} variant={"outlined"}
                                       value={word.taboos ? word.taboos[3] : ""}/>
                            <br/>
                            <TextField color={"primary"} disabled={true} variant={"outlined"}
                                       value={word.taboos ? word.taboos[4] : ""}/>
                            <br/>
                            <TetonButton text={"Neues Wort"} variant={"contained"} color={"primary"}
                                         onClick={() => getWord()} disabled={false} loading={loading}
                                         margin={"2% 0 0 0"}/>
                        </div>
                    }/>
                </div>
            }/>
        </div>
    );
}

export default App;

我想点击按钮,然后获取一个单词并将其设置到字段中。这很好用。我还需要不要忽略 href 参数,因为当页面加载了该 id 时,我需要页面加载 href 中的 id。但是,当单击按钮时,我不希望这种情况发生。所以我读到 [] 作为使用效果的依赖数组只会在渲染时运行一次。但是,现在,一旦单击按钮或使用href 中的 id 加载页面,我就会无限重新加载。我怎样才能阻止这个? deepCompare 只是为了让我也可以检查对象。我也尝试了依赖数组的所有组合。这似乎很讨厌我。

感谢您的帮助!

编辑:深度比较代码

import * as _ from "lodash";
import { useEffect, useRef } from "react";

const deepCompareEquals = (a, b) => {
    return _.isEqual(a, b);
};

const useDeepCompareMemoize = value => {
    const ref = useRef();

    if (!deepCompareEquals(value, ref.current)) {
        ref.current = value
    }

    return ref.current
};

const useDeepCompareEffect = (callback, dependencies) => {
    useEffect(callback, useDeepCompareMemoize(dependencies));
};

export default useDeepCompareEffect;

【问题讨论】:

  • 您也可以发布deepCompare 代码吗?
  • 尝试用 useEffect 替换 useDeepCompareEffect 并检查是否复制了相同的行为?
  • 是的。 useDeepCompareEffect 只是尝试修复它。然而,行为是相同的。

标签: reactjs reload use-effect


【解决方案1】:

刚刚发现。

您正在使用window.location.href = href.split("/")[0] + id;,它将始终重新加载页面,当然这将以您提到的问题结束。

这些事情你必须使用react router

【讨论】:

  • 谢谢!我相信反应路由器会做得更好。我不知道怎么做。我用 useLocation 和 location.pathname 替换了我的逻辑以获取我需要的参数。但是页面仍然会重新加载而不会停止。将 Path 和 word 作为依赖项添加到钩子中也不会改变这一点。您能否给我一个简单的例子来说明它需要如何实现?
  • @Timbo 搜索history.push。这将完成工作
  • 你救了我的命!非常感谢你。这是非常明显的。我只是没看到。我用history.push(window.location.href.split("/")[0] + id);替换了window.location.href = href.split("/")[0] + id;
  • 很高兴我帮助了 :)
  • 我永远不会发现。一千个祝福你的房子!
猜你喜欢
  • 1970-01-01
  • 2022-11-26
  • 2013-06-17
  • 1970-01-01
  • 1970-01-01
  • 2017-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多