在 React 中使用自定义钩子获取多个表中的数据时,自定义 ContextProvider

我有多个小表,当应用程序更新相应的表时,我希望能够写入/读取/更新我的组件(我们暂时可以认为它是一个单用户应用程序)。

我受到这个问题的启发,在我的应用程序中编写了一个自定义提供程序和关联的用于数据获取(并最终发布)的钩子:React useReducer async data fetch

我想出了这个:

import React from "react";

import { useContext, useState, useEffect } from "react";

import axios from "axios";


const MetadataContext = React.createContext();


function MetadataContextProvider(props) {

  let [metadata, setMetadata] = useState({});


  async function loadMetadata(url) {

    let response = await axios.get(url);

    // here when I console.log the value of metadata I get {} all the time

    setMetadata({ ...metadata, [url]: response.data });

  }


  async function postNewItem(url, payload) {

    await axios.post(url, payload);

    let response = await axios.get(url);

    setMetadata({ ...metadata, [url]: response.data });

  }


  return (

    <MetadataContext.Provider value={{ metadata, loadMetadata, postNewItem }}>

      {props.children}

    </MetadataContext.Provider>

  );

}


function useMetadataTable(url) {

  // this hook's goal is to allow loading data in the context provider

  // when required by some component

  const context = useContext(MetadataContext);


  useEffect(() => {

    context.loadMetadata(url);

  }, []);


  return [

    context.metadata[url],

    () => context.loadMetadata(url),

    (payload) => context.postNewItem(url, payload),

  ];

}


function TestComponent({ url }) {

  const [metadata, loadMetadata, postNewItem] = useMetadataTable(url);

  // not using loadMetadata and postNewItem here


  return (

    <>

      <p> {JSON.stringify(metadata)} </p>

    </>

  );

}



(代码应该在 CRA 上下文中运行,两个 API 都可以替换为几乎任何 API)


当我运行它时,会在两个端点(/api/capteur 和 /api/observation)上触发请求,但我期望 MetadataContextProvider 中的元数据对象有 2 个键:&ldquo;/api/capteur&rdquo;和&ldquo;/ api/observation&rdquo;,只显示最后一次请求的内容。


当我在 loadMetadata 函数中 console.log 元数据时,元数据始终具有初始状态挂钩值,即 {}。


我对 React 还很陌生,我努力尝试过,但我真的不明白这里发生了什么。有人可以帮忙吗?


慕莱坞森
浏览 118回答 1
1回答

一只萌萌小番薯

您的问题是如何使用 更新metadata对象setMetadata。metadata在您的上下文中通过更新对象的操作loadMetadata分别由两个“实例”完成:TestComponent#1 和TestComponent#2。它们都可以访问metadata上下文中的对象,但它们不会立即同步,因为useState的 setter 函数是异步工作的。解决您的问题的简单方法称为功能更新。 useState的 setter 还提供了一个回调函数,它将使用(我在这里过于简单化)“最新”状态。在您的上下文提供者中:async function loadMetadata(url) {  let response = await axios.get(url);  setMetadata((existingData) => ({ ...existingData, [url]: response.data }));  // instead of  // setMetadata({ ...metadata, [url]: response.data });}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript