简体   繁体   English

如何从 Provider 共享数据到 function react

[英]How to share data from Provider to function react

I've created an NPM library that shares multiple util functions.我创建了一个共享多个实用程序函数的 NPM 库。 One of which is to call our endpoints.其中之一是调用我们的端点。 I've included Axios in my NPM library, but I'm stuck being able to set the Axios.create instance globally.我已将 Axios 包含在我的 NPM 库中,但我无法在全局范围内设置Axios.create实例。

I initially thought I could create a Provider and set a context , however, as my API function isn't within a hook, I cannot access the context.我最初以为我可以创建一个Provider并设置一个context ,但是,由于我的 API function 不在钩子内,我无法访问上下文。 This is my first NPM library so unfamiliar with what is best practice.这是我的第一个 NPM 库,所以不熟悉什么是最佳实践。

// Provider.ts

export default function Provider({ children, config }: ProviderProps) {
  window.config = config;
  return (
    <ContextConfig.Provider value={config}>{children}</ContextConfig.Provider>
  );
}

^ Above, I tried using context API, setting a global variable, etc. ^ 上面,我尝试使用上下文 API,设置全局变量等。

// api.ts

import Axios, { AxiosInstance, AxiosPromise, Cancel } from 'axios';

const axiosInstance = Axios.create(window.config);

const api = (axios: AxiosInstance) => ({
  get: <T>(url: string, config: ApiRequestConfig = {}) =>
    withLogger<T>(withAbort<T>(axios.get)(url, config)),
});

export default api(axiosInstance)

^ Above, tried to use the global variable window.config , however, it is undefined . ^ 上面,尝试使用全局变量window.config ,但是,它是undefined的。 Also tried converting the export to a hook to allow reading the context, however, getting errors around unsafe usage of hooks.还尝试将导出转换为钩子以允许读取上下文,但是,在钩子的不安全使用方面出现错误。

// index.ts

import api from './api';
import Provider from './Provider';

export { api, Provider };

The only way I can think about handling this now is using Local Storage, very much open to advise.我现在可以考虑处理这个问题的唯一方法是使用本地存储,非常愿意提供建议。

Cheers干杯

You absolutely should be able to bind your variable to the window .您绝对应该能够将您的变量绑定到window

What I think has actually happened is that api.ts has been initiated before you set window.config , hence why it is undefined .我认为实际发生的是api.ts在您设置window.config之前已经启动,因此它是undefined的。 If you converted api.ts default export to a function you'll be able to get the value of window.config on each call.如果您将api.ts默认导出转换为 function,您将能够在每次调用时获得window.config的值。 IE; IE;

// api.ts

import Axios, { AxiosInstance, AxiosPromise, Cancel } from 'axios';

const api = (axios: AxiosInstance) => ({
  get: <T>(url: string, config: ApiRequestConfig = {}) =>
    withLogger<T>(withAbort<T>(axios.get)(url, config)),
});

export default () => {
 const axiosInstance = Axios.create(window.config);
 return api(axiosInstance)
}

This may be a little less performant as you'll be calling Axios.create on each call, however, it shouldn't be too impactful.这可能会稍微降低性能,因为您将在每次调用时调用Axios.create ,但是,它的影响应该不会太大。

Do you need the config for anything except your Axios instance?除了 Axios 实例之外,您是否需要任何配置?

Why not just create a Provider / Context setup that handles your api object for you?为什么不为您创建一个处理您的 api object 的提供者/上下文设置?

// Create a context for the api
const ApiContext = createContext({});

// Create a Provider component.
const ApiProvider = ({ config }) => {

    // recreate the api every time the provided configuration changes.
    const api = useMemo(() => {
        // create axios instance using the provided config.
        const axiosInstance = Axios.create(config);

        // create API object
        return {
            get: <T,>(url: string, apiConfig: ApiRequestConfig = {}) => withLogger<T>(withAbort<T>(axiosInstance.get)(url, apiConfig))
        };
    }, [config] /* dependency array - determines when api will be recomputed */)

    return (
        <ApiContext.Provider value={api}>
            {children}
        </ApiContext.Provider>
    );
};

const useApi = () => {
    // retrieve configured API from context.
    const api = useContext(ApiContext);

    return api;
}

// Example component to show how to retrieve api for use.
const Example = () => {
    // retrieve configured API from context.
    const api = useContext(ApiContext);

    //OR

    const api = useApi();

    // use api here

    return (
        <div>
            Content goes here
        </div>
    )
}

// App component to show providing config for API.
const App = () => {

    // Create config (should only update reference when values need to change)
    const config = useMemo(() => ({
        // add config here
    }), []);

    return (
        // pass config to API Provider.
        <ApiProvider  config={config}>
            <Example />
        </ApiProvider>
    )
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM