useEffect никогда не перестает работать - PullRequest
1 голос
/ 11 июля 2020

Я уверен, что этот вопрос задавали миллион раз. И я просмотрел не менее 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 не игнорировался, потому что мне нужна страница для загрузки идентификатора в href, когда страница загружается с этим идентификатором. Однако, когда была нажата кнопка, я не хочу, чтобы это произошло. Итак, я прочитал, что [] как массив зависимостей для использования эффект будет запускаться только один раз при рендеринге. Однако теперь, когда нажимается кнопка или страница загружается с идентификатором href, я получаю бесконечные перезагрузки. Как я могу это остановить? deepCompare - это просто, чтобы я мог также проверять объекты. Также я пробовал все комбинации массивов зависимостей. Кажется, это просто меня ненавидит.

Спасибо за вашу помощь!

EDIT: Deep Compare Code

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;

1 Ответ

1 голос
/ 11 июля 2020

Только что заметил.

Вы используете window.location.href = href.split("/")[0] + id;, который всегда будет перезагружать страницу, и, конечно же, это закончится проблемой, о которой вы упомянули.

Вы должны использовать react router для эти вещи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...