当前位置: 首页 > 知识库问答 >
问题:

将值从自定义挂钩保存到状态

荣轶
2023-03-14

我正试图将一个值从一个定制钩子(为服务器获取数据)保存到带有useState的功能组件状态,因为我以后需要更改这个值,更改后需要重新加载。因此,理想的行为是:

  1. 将状态变量设置为自定义挂钩中的值

我尝试的是:

>

  • 设置useState的初始值到我的钩子:const[data, setData]=useState

    在useffect()挂钩中设置状态:

    useEffect(()=>{
        const d = useLoadData(id).data
        setData(d)
    }, [id])
    

    但这显示了错误警告:错误:无效的钩子调用。钩子只能在函数组件的主体内部调用。

    这样做:

    const [data, setData] = useState<DocumentType[]>([])
    const dataFromServer = useLoadData(id).data
    
    useEffect(()=>{
      if (dataFromServer){
        setData(dataFromServer)
      }
    }, [dataFromServer])
    

    导致:错误:超出最大更新深度。这可能发生在一个组件在use效应中调用setState时,但是use效应要么没有依赖数组,要么其中一个依赖关系在每次渲染时都会更改。

    对于我的用例来说,什么是合适的解决方案?


  • 共有1个答案

    华易安
    2023-03-14

    看起来您的自定义钩子每次使用时都会返回一个新数组。

    解决方案1:更改钩子以返回数组的“缓存”实例。

    function useLoadData(id) {
      const [data, setData] = useState([]);
    
      useEffect(() => {
        loadData(id).then(setData);
      }, [id]);
    
      // good
      return data;
    
      //bad
      //return data.map(...)
    
      //bad
      //return data.filter(...)
    
      //etc
    }
    

    codesandbox.io链接

    解决方案2:更改钩子以接受setData作为参数。

    function useLoadData(id, setData) {
      useEffect(() => {
        loadData(id).then(setData);
      }, [id]);
    }
    

    在这里,我告诉钩子在哪里存储数据,以便组件中的自定义钩子和按钮都可以写入同一个地方。

    codesandbox.io链接

    完整示例:

    import React from "react";
    import ReactDOM from "react-dom";
    import { useState, useEffect } from "react";
    
    // simulates async data loading
    function loadData(id) {
      return new Promise((resolve) => setTimeout(resolve, 1000, [id, id, id]));
    }
    
    // a specialized 'stateless' version of custom hook
    function useLoadData(id, setData) {
      useEffect(() => {
        loadData(id).then(setData);
      }, [id]);
    }
    
    function App() {
      const [data, setData] = useState(null);
    
      useLoadData(123, setData);
    
      return (
        <div>
          <div>Data: {data == null ? "Loading..." : data.join()}</div>
          <div>
            <button onClick={() => setData([456, 456, 456])}>Change data</button>
          </div>
        </div>
      );
    }
    
    ReactDOM.render(<App />, document.getElementById("container"));
    
     类似资料:
    • 我在关注丹·阿布拉莫夫的这篇文章: https://overreacted.io/making-setinterval-declarative-with-react-hooks/ 在本文中,Dan制作了一个自定义的useInterval钩子,以创建一个动态的setInterval。 钩子看起来像这样: 但有一部分我不明白,那就是: 我理解,如果延迟更改,则调用此useEffect。回调被分配给ti

    • 问题内容: 我有一个新闻和一个消息。所述含有选择加入到阵列时teamObjects的的tableView。我想将此数组添加到其中,以便可以从其中包含需要teamObjects的url请求的访问它们。但是我不断得到: “试图为关键团队插入非财产列表对象(“”) 如果有比将其存储在更好的方法,我愿意接受其他建议 方法 我的对象 问题答案: 实际上,您将需要将自定义对象归档到其中,然后将其保存到用户默认

    • 问题内容: 我目前正在尝试将自定义Swift类保存到NSUserDefaults。这是我的游乐场代码: 运行代码时,出现以下错误 执行被中断,原因:信号SIGABRT。 在最后一行(…) 在带有消息的应用程序中,相同的代码也会崩溃 “属性列表对于格式无效:200(属性列表不能包含’CFType’类型的对象)” 有人可以帮忙吗?我在Maverick上使用Xcode 6.0.1。谢谢。 问题答案: 正

    • 我有一个小的井字游戏,一切都很好,除了我正在努力寻找在代码中放置完成功能的位置。让我给你看; 这基本上是整个游戏,我在另一个文件中有一个整理函数,就像这样; 完成功能也可以正常工作,但是由于useState是异步工作的,我知道这一点,我正在努力把它放在哪里。如果我把点击功能放在里面,它就不能对新的状态做出反应,只能对之前的状态做出反应。如果我把外面加上只是if语句,它会说渲染太多,因为我正在设置获

    • 问题内容: 我正在制作一个使用AVFoundation拍照的应用程序,我想将它们保存到自定义相册中,然后查询并显示在我的应用程序中。(除非用户希望,否则我不希望它们出现在一般的照片胶卷中)我真的找不到任何东西可以显示在Swift中如何做到这一点……或根本没有。我应该有其他方法吗? 我在SO上找到了这个示例,但是对我来说这没有意义,我无法使其正常工作。 任何帮助/说明都将非常棒! 问题答案: 这是我

    • 我正在尝试使用状态将一个表单输入值复制到另一个表单输入值,但状态没有更新 我创建了一个带有按钮的表单,其中左侧表单输入的值应复制到右侧表单输入。这是我的代码: 无论我做什么,dbSecName的状态都不会改变。我试着设置一个新的常量。我尝试使onclick函数异步并等待。如果我为我试图设置的变量的值添加,我可以正确地看到它,但是dbSecName的console.log总是显示原始值。 我真的不知