【问题标题】:Using React hooks to set state and local storage and React is saying I am making too many calls使用 React 钩子设置状态和本地存储,React 说我打了太多电话
【发布时间】:2021-08-21 21:09:40
【问题描述】:

我有一个小型 React 组件,它仅使用富文本编辑器 (TinyMCE) 来编辑 Web 应用程序上显示的文本字段中的值。

我发现如果我输入太快或太多,我会收到这个错误:

未捕获的错误:超出最大更新深度。这可能发生在一个 组件在 componentWillUpdate 内重复调用 setState 或 componentDidUpdate.

但我没有使用componentWillUpdatecomponentDidUpdate

所以我不确定 React 为什么会这样告诉我。

我尝试过修复,但没有任何帮助。

如果有任何见解,我将不胜感激! :)

这是我的 React 组件:

import React, { useState, useEffect } from 'react';
import { Editor } from '@tinymce/tinymce-react';
import axios from 'axios';

const App = (props) => {
    const [engineText, setEngineTextState] = useState(props.engineText || "Describe your engine...");
    const [engineId, setEngineIdState] = useState(props.engineId);
    var edValue = '';

    // first check local storage to see if they already have typed something...use engineId as the unique key
    if (localStorage.getItem(engineId)) {
        edValue = localStorage.getItem(engineId);
    } else {
        edValue = engineText;
    }

    const [engineState, setEngineState] = useState(edValue);

    // set the local storage in case user navigates away and then comes back we don't lose what they wrote
    useEffect(() => {
        localStorage.setItem(engineId, engineState)
    }, [engineState]);

    // update database
    const updateEngineText = (content) => {
        const request = axios.put(`/api/EngineManagementConsole/${engineId}/engineText`, JSON.stringify(content), {
            headers: {
                'Content-Type': 'application/json'
            }
        });
        setEngineState(content);
    }
    return (
        <Editor
            initialValue={edValue}
            init={{
                height: 500,
                menubar: 'file edit view insert format tools table help',
                plugins: [
                    'searchreplace visualblocks code fullscreen',
                ]
            }}
            value={engineState}
            onEditorChange={updateEngineText}
        />
    )
}

export default App;

【问题讨论】:

    标签: reactjs axios react-hooks local-storage


    【解决方案1】:

    您的组件将检查localStorage 并在每次渲染时设置edValue 的值。这将作为 initialValue 属性传递给 Editor,因此它将导致 Editor 组件重新渲染。

    由于这只是一个初始值,您可能打算只评估一次。我们可以使用useMemo

    您的edValue 派生自engineIdengineText,因此它们应该是useMemo 的依赖项。如果其中任何一个变量发生变化,它将被重新评估。

    当您似乎没有在任何地方更新它们的状态时,将道具 engineIdengineText 复制为状态似乎很愚蠢。直接使用道具即可。

    const App = ({engineId, engineText = "Describe your engine..."}) => {
    
        const edValue = useMemo( () => {
             // function to create the value
             return localStorage.getItem(engineId) || engineText;
             // dependencies array
             }, [engineId, engineText]
        );
    
        const [engineState, setEngineState] = useState(edValue);
    ...
    

    注意:我不确定是否是唯一问题,可能还有其他问题导致错误。

    【讨论】:

    • 谢谢!我需要摆脱我使用的useEffect() 吗?另外,我还假设我不再需要这条线:var edValue = ''; 我会测试一下!谢谢!
    • 再次嗨,所以我测试了这个,它不再让我出错了。它工作得更好,但我注意到当我在组件中编辑文本,离开页面,然后返回时,文本仍然显示"Describe your engine..."。因此,出于某种原因,它没有从存储中获取新文本。现在,如果我刷新页面,它会得到新的文本。所以我想知道是否需要将 useEffect() 声明放回......因为那是我有 localStorage.setItem 的地方?谢谢!
    • 仍然没有运气:(我最终没有重新添加useEffect() 语句。但我确实将localStorage.setItem(engineId, engineState) 移动到updateEngineText() 函数,认为这会起作用。但是,它正在将正确/更新的文本保存到数据库和本地存储中。但由于某种原因,当我离开,然后再次返回时,它显示“描述你的引擎......”而不是存储在 localStorage 中的内容,直到我刷新手动页面。
    猜你喜欢
    • 2017-06-11
    • 1970-01-01
    • 2020-05-23
    • 2021-10-26
    • 2021-06-28
    • 2020-05-12
    • 1970-01-01
    • 1970-01-01
    • 2020-04-05
    相关资源
    最近更新 更多