问题描述
我正在尝试通过使用一种简单的服务来抽象我的API调用,该服务提供了一种非常简单的方法,它只是一个HTTP调用.我将此实现存储在React Context中,并在我的_app.js
中使用其提供程序,以便该API在全球范围内可用,但是在实际使用我的页面中的上下文时遇到了问题.
I am attempting to abstract my API calls by using a simple service that provides a very simple method, which is just an HTTP call. I store this implementation in a React Context, and use its provider inside my _app.js
, so that the API is globally available, but I have a problem at actually consuming the context in my pages.
页面/_app.js
import React from 'react'
import App, { Container } from 'next/app'
import ApiProvider from '../Providers/ApiProvider';
import getConfig from 'next/config'
const { serverRuntimeConfig, publicRuntimeConfig } = getConfig()
export default class Webshop extends App
{
static async getInitialProps({ Component, router, ctx }) {
let pageProps = {}
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx)
}
return { pageProps }
}
render () {
const { Component, pageProps } = this.props
return (
<Container>
<ApiProvider endpoint={publicRuntimeConfig.api_endpoint}>
<Component {...pageProps} />
</ApiProvider>
</Container>
);
}
}
服务/Api.js
import fetch from 'unfetch'
function Api (config)
{
const apiUrl = config.endpoint;
async function request (url) {
return fetch(apiUrl + '/' + url);
};
this.decode = async function (code) {
const res = request('/decode?code=' + code);
const json = await res.json();
return json;
}
return this;
}
export default Api;
Providers/ApiProvider.js
import React, { Component } from 'react';
import Api from '../Services/Api';
const defaultStore = null;
class ApiProvider extends React.Component
{
state = {
api: null
};
constructor (props) {
super(props);
this.state.api = new Api({ endpoint: props.endpoint });
}
render () {
return (
<ApiContext.Provider value={this.state.api}>
{this.props.children}
</ApiContext.Provider>
);
}
}
export const ApiContext = React.createContext(defaultStore);
export default ApiProvider;
export const ApiConsumer = ApiContext.Consumer;
export function withApi(Component) {
return function withApiHoc(props) {
return (
<ApiConsumer>{ context => <Component {...props} api={context} /> }</ApiConsumer>
)
}
};
pages/code.js
import React, { Component } from 'react';
import Link from 'next/link';
import { withApi } from '../Providers/ApiProvider';
class Code extends React.Component
{
static async getInitialProps ({ query, ctx }) {
const decodedResponse = this.props.api.decode(query.code); // Cannot read property 'api' of undefined
return {
code: query.code,
decoded: decodedResponse
};
}
render () {
return (
<div>
[...]
</div>
);
}
}
let hocCode = withApi(Code);
hocCode.getInitialProps = Code.getInitialProps;
export default hocCode;
问题是我无法访问消耗的上下文.我可以直接在getInitialProps
中进行直接fetch
调用,但是我想通过使用也需要可配置URL的小函数来对其进行抽象.
The problem is that I am unable to access the consumed context. I could just make a direct fetch
call within my getInitialProps
, however I wanted to abstract it by using a small function that also takes a configurable URL.
我在做什么错了?
推荐答案
您不能以 static 方法getInitialProps
的方式访问提供程序的实例,该方法在React树之前被调用(当您的提供程序可用时).
You can't access an instance of your provider in as static method getInitialProps
, it was called way before the React tree is generated (when your provider is available).
我建议您将API的 Singelton 保存在API模块中,并通过常规导入在getInitialProps
方法内使用它.
I would suggest you to save an Singelton of your API in the API module, and consume it inside the getInitialProps
method via regular import.
或者,您可以将其注入到_app
getInitialProps中的componentPage中,如下所示:
Or, you can inject it to your componentPage inside the _app
getInitialProps, something like that:
// _app.jsx
import api from './path/to/your/api.js';
export default class Webshop extends App {
static async getInitialProps({ Component, router, ctx }) {
let pageProps = {}
ctx.api = api;
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx)
}
return { pageProps }
}
render () {
const { Component, pageProps } = this.props
return (
<Container>
<Component {...pageProps} />
</Container>
);
}
}
// PageComponent.jsx
import React, { Component } from 'react';
class Code extends React.Component
{
static async getInitialProps ({ query, ctx }) {
const decodedResponse = ctx.api.decode(query.code); // Cannot read property 'api' of undefined
return {
code: query.code,
decoded: decodedResponse
};
}
render () {
return (
<div>
[...]
</div>
);
}
}
export default Code;
这对您有意义吗?
这篇关于使用HOC访问Next.js getInitialProps中消耗的React.Context的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!