【发布时间】:2019-07-09 14:17:13
【问题描述】:
我正在尝试使用一个简单的服务来抽象我的 API 调用,该服务提供了一个非常简单的方法,它只是一个 HTTP 调用。我将此实现存储在 React Context 中,并在我的 _app.js 中使用它的提供程序,以便 API 全局可用,但我在实际使用页面中的上下文时遇到了问题。
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 的小函数来抽象它。
我做错了什么?
【问题讨论】:
-
我在尝试使用
Context.ConsumerAPI 访问功能组件中的上下文时遇到了类似的问题。您是否尝试过使用static contextType = ApiContext将其转换为类组件。不是一个解决方案,但它会帮助你找出这是否是问题 -
探测的是 getInitialProps 是一个静态方法,因此你不能从它里面访问类实例属性
-
@ShubhamKhatri 哦,对了……这太明显了。那我怎么能做这样的事情呢?我需要将它作为我的 HOC 的 getInitialProps 的参数传递,对吗?这也是我尝试过的,但是我无法以编程方式访问 React.Context 数据,如果我用消费者上下文包装我的组件,getInitialProps 将不会被正确调用。
标签: javascript reactjs next.js react-context