UrqlClient headers are not showing/updating - reactjs

Im using Urql as my Graphql Client for fetching data from my Shopify store but my headers are not showing up on my network requests.
The weird thing is that even if i dont send any headers, this x-shopify-storefront-access-token is still showing up as part of my request headers in the network tab. If i put any random key, value pair of headers they wont even show up.
I dont understand what is going on?
client.js
import { createClient } from 'urql'
export const urqlClient = createClient({
url: `https://${process.env.GATSBY_SHOPIFY_STORE_URL}/api/2022-07/graphql.json`,
fetchOptions: () => {
return {
headers: {
'X-Shopify-Storefront-Access-Token':
'my access token string',
},
}
},
})
And im providing it at the root level for every page
gatsby.browser.js
import * as React from 'react'
import { StoreProvider } from './src/context/store-context'
import './src/styles/reset.css'
import './src/styles/variables.css'
import './src/styles/global.css'
import { urqlClient } from './src/context/client'
import { Provider } from 'urql'
export const wrapRootElement = ({ element }) => (
<Provider value={urqlClient}>
<StoreProvider>{element}</StoreProvider>
</Provider>
)

Related

Creating a new apollo client that depends on a value from a global state in React

I am working on a react project and I want to setup an apollo client and pass access token to headers but my access token is in my globale state. I have tried creating the client within the component but I ended up with an infinite loop.
import {
ApolloClient,
ApolloProvider as Provider,
InMemoryCache,
} from '#apollo/client'
import React, { useEffect } from 'react'
import { StateProviderProps } from './../../types'
import { useAuthTokenState } from './../authToken/AuthTokenState'
const client = new ApolloClient({
uri: 'https://subdomain.domain.com/graphql',
cache: new InMemoryCache(),
// headers: {
// Authorization: 'Bearer' + state?.accessToken,
// },
})
const ApolloProvider = ({ children }: StateProviderProps) => {
const { state } = useAuthTokenState()
return <Provider client={client}>{children}</Provider>
}
export default ApolloProvider
i am looking for any idea that could help make this work.
thanks

TypeError: Cannot read property 'useContext' of null nextjs

I am going to get user from context and use it in header in nextjs strapi apollo graphql project User is accessable in App function but outside its giving above error. Is context values accessable outside function if yes how can I access it if no how to structure it so that I can use it in request header.
import "../styles/globals.css";
import Layout from "../components/Layout";
import { Provider } from "../context/AppContext";
import Cookies from "js-cookie";
import withApollo from "next-with-apollo";
import { BACKEND_URL } from "../helpers";
import React, { useContext } from "react";
import { AppContext } from "../context/AppContext";
import { ApolloClient, ApolloProvider, InMemoryCache } from "#apollo/client";
const { user } = useContext(AppContext);
console.log("user from context in _app", user);
function App({ Component, pageProps, apollo }) {
return (
<Provider>
<ApolloProvider client={apollo}>
<Layout>
<Component {...pageProps} />
</Layout>
</ApolloProvider>
</Provider>
);
}
export default withApollo(({ initialState, headers }) => {
return new ApolloClient({
uri: `${BACKEND_URL}/graphql`,
cache: new InMemoryCache().restore(initialState || {}),
...(user && {
headers: {
authorization: `Bearer ${user.token}`,
},
}),
});
})(App);
On my machine, Next.js didn't work if, in Windows Terminal, the disk letter (for example, C:) of the "current directory" was written in lowercase (as c: in this example).
After I changed the current directory from c:\dev\project to C:\dev\project, the error went away.
Source: https://github.com/vercel/next.js/issues/7626#issuecomment-541430221

AppSync client doesn't returns data

I need some pro advice here because I am going a little crazy. I am trying to create an graphql client combining Apollo and AppSync. I've done this approach before, but it is not working in another project I've just created. My situation is the following:
It seems that the client is connecting to my AppSync server (it is returning the __typename in the data), but It is not returning anything else. This is an example of the client use and the response I am getting:
const response = client
.query({
query: gql`
query MyQuery {
listSys_users {
items {
email
name
active
user_id
}
}
}
`,
})
.then(console.log);
I've tried to call the server making a POST request with axios and it works perfectly fine:
const axiosWrapper = () => {
const defaultOptions = {
baseURL: envConfig.graphQLUrl,
headers: { 'x-api-key': envConfig.graphQLApiKey },
};
const instance = axios.create(defaultOptions);
return instance;
};
axiosWrapper.post('', {
query: `
query MyQuery {
listSys_users {
items {
email
name
active
user_id
}
}
}
`,
}).then(console.log);
Now that You know the situation I will share my attempts on this:
Right know I have something like this:
The client.js:
import { ApolloLink } from 'apollo-link';
import { HttpLink } from 'apollo-link-http';
import ApolloClient from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { createAuthLink } from 'aws-appsync-auth-link';
import config from './configs/env';
const { graphQLUrl, region, graphQLApiKey } = config;
const auth = {
type: 'API_KEY',
apiKey: graphQLApiKey,
// jwtToken: async () => (await Auth.currentSession()).getAccessToken().getJwtToken(),
};
const authMiddleware = new ApolloLink((operation, forward) => {
// add the authorization to the headers
operation.setContext(({ headers = {} }) => ({
headers: {
...headers,
'x-api-key': 'MY_API_KEY',
accept: 'application/json, text/plain, */*',
'content-type': 'application/json;charset=UTF-8',
},
}));
return forward(operation);
});
const client = new ApolloClient({
link: ApolloLink.from([authMiddleware, new HttpLink({ uri: graphQLUrl })]),
cache: new InMemoryCache(),
});
export default client;
The App.js:
import 'react-app-polyfill/ie11';
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import { ApolloProvider } from 'react-apollo';
import { Provider } from 'react-redux';
import App from './App';
import store from './store/reducers/rootReducer';
import './helpers/Translation/i18n';
import Login from './pages/Login';
import client from './client';
ReactDOM.render(
<ApolloProvider client={client}>
<BrowserRouter>
<Provider store={store}>
<Login>
<App />
</Login>
</Provider>
</BrowserRouter>
</ApolloProvider>,
document.getElementById('root')
);
Package.json:
"apollo-cache-inmemory": "^1.6.6",
"apollo-client": "^2.6.10",
"apollo-link": "^1.2.14",
"apollo-link-http": "^1.5.17",
"aws-amplify": "^3.3.27",
"aws-amplify-react-native": "^4.3.2",
"aws-appsync": "^4.1.4",
"aws-appsync-react": "^4.0.10",
"graphql": "^15.6.1",
"graphql-tag": "^2.12.5",
In this case the response is the same, it is connecting but it returns null in the items.
Yes, I know, I should use the creatAuthLink from aws-appsync-auth-link. Thats my second attempt.
My second attempt was using createAuthLink, but when I tried to use it It throw this error:
./node_modules/aws-appsync-auth-link/lib/auth-link.js
Module not found: Can't resolve '#apollo/client/core' in '/Users/VIU/GEOACTIO/smart-pockets/smart-pockets-react/node_modules/aws-appsync-auth-link/lib'
So I ended up installing and using the #apollo dependencies:
client.js:
import { ApolloClient, ApolloLink, HttpLink, InMemoryCache } from '#apollo/client';
import { createAuthLink } from 'aws-appsync-auth-link';
import config from './configs/env';
const { graphQLUrl, region, graphQLApiKey } = config;
const auth = {
type: 'API_KEY',
apiKey: graphQLApiKey
};
const client = new ApolloClient({
link: ApolloLink.from([
createAuthLink({ auth, region, url: graphQLUrl }),
new HttpLink({ uri: graphQLUrl }),
]),
cache: new InMemoryCache(),
});
export default client;
package.json:
"#apollo/client": "^3.4.16",
...all the same
Still getting the same response.. I won't bother You with more attempts. I've tried all the possible combination between these and more apollo / graphql / appsync dependencies and the outcome is always the same: either I get the null response with the __typename or I get a dependencies error.
NOTE: I've noticed that when using axios, the lambda attached to that resolver fires up as it should, but when using another approach, the lambda doesn't fire up, so obviously it won't return any data.
I know it is a long post but I am trying to explain the best I can my situation. And I can't create a sandbox code because I don't want to expose the API credentials.. Any ideas of what I am doing wrong?
Thanks in advance!!

How to serve different versions of the same web app based on subdomain - CSR w/ React

I'm currently trying to create an application that will serve a client side web application that will be mostly the same, but slightly different based on the different subdomains. For example, client1.website.com vs client2.website.com -- same base app, slightly different branding and content.
Currently, I have attempted to save this content by fetching static JSON files that contain the differences between the two sites. They are made as a normal GET call to the local server and then applied as a 'content' key in the state object of the application. The problem I am having is that I am unable to reference parts of the content because React attempts to render them before the parent application is finished applying the 'content' state.
Is this architecture the wrong way to go about things or is there a solution that I just haven't found yet?
I've posted my code below to try and show what I'm doing, I've used a third party state library to try and simplify what something like redux would do when full fleshed out:
// Index.js (Contains my store)
import React from "react";
import axios from "axios";
import ReactDOM from "react-dom";
import { StoreProvider, createStore, thunk, action } from "easy-peasy";
import "./index.css";
import App from "./pages/App";
const store = createStore({
company: {
contentType: "default",
baseContent: {},
partnerContent: {},
setContentType: action((state, payload) => {
state.contentType = payload;
}),
setContentData: action((state, payload) => {
state[payload.type] = payload.data;
}),
loadContent: thunk(async (actions, payload) => {
try {
if (payload !== "base") {
actions.setContentType(payload);
}
const partnerData = await axios.get(`content/${payload}.json`);
const baseData = await axios.get(`content/base.json`);
actions.setContentData({
data: partnerData.data,
type: "partnerContent",
});
actions.setContentData({
data: baseData.data,
type: "baseContent",
});
} catch (e) {
throw e;
}
}),
},
});
ReactDOM.render(
<StoreProvider store={store}>
<App />
</StoreProvider>,
document.getElementById("root")
);
//App.js (Where I attempt to suspend until my data is loaded into state)
import React, { useEffect, Suspense } from "react";
import { useStoreActions } from "easy-peasy";
import Header from "../components/Header";
import Content from "../components/Content";
import "./App.css";
const content = "default";
const App = () => {
const { loadContent } = useStoreActions((actions) => ({
loadContent: actions.payforward.loadContent,
}));
useEffect(() => {
async function fetchData() {
await loadContent(content);
}
fetchData();
}, [loadContent]);
return (
<div className='App'>
<Header />
<Content />
</div>
);
};
export default App;
//Header.js (Where I attempt to reference some URLs from the JSON file applied to my state)
import React, { useMemo } from "react";
import { useStoreState } from "easy-peasy";
const Header = () => {
//Unable to access state because it's currently undefined until the JSON is loaded in
const headerURLs = useStoreState(
(state) => state.company.partnerContent.routes.header.links
);
return (
<div>
<h1>This is the Header</h1>
{/* {headerURLs.map((url) => {
return <p>{url}</p>;
})} */}
</div>
);
};
export { Header as default };

I want to set preauthorizeApiKey in swagger-ui-react application auto authorized

I have below code where I have set preauthorizeApiKey and it's working fine and calls to APIs is also working. APIs need header "Authorization: Bearer xxxxxxxxxxx". I had key stored in react store and reading using getToken().
import React from 'react';
import SwaggerUI from 'swagger-ui-react';
import swaggerSpec from '../../swagger.json';
import { getToken } from '../../api/utils'
export const complete=function(swaggerUi)
{
let token = getToken();
swaggerUi.preauthorizeApiKey('bearerAuth', token.Token);
}
const ApiDocs = () => {
return <SwaggerUI spec={swaggerSpec} onComplete={(swaggerUi) => complete(swaggerUi)} />
};
export default ApiDocs;
Below is my route configuration:
<Route path="/api-docs" component={ApiDocs} />
I don't need to click on Authorize button on swagger UI screen and it is auto Authorized. Just wanted to share for any comment/suggestion/improvement.
The onComplete props should be a function. Please see the document here.
import React from "react";
import SwaggerUI from "swagger-ui-react";
import swaggerSpec from "../../swagger.json";
import { getToken } from "../../api/utils";
export const complete = function (swaggerUi) {
const token = getToken();
swaggerUi.preauthorizeApiKey("bearerAuth", token.Token);
};
const ApiDocs = () => {
return <SwaggerUI spec={swaggerSpec} onComplete={complete} />;
};
export default ApiDocs;

Resources