How to resolve No `Web3Provider Found` Exception web3-react? - reactjs

I am getting a No <Web3Provider ...> Found. when my React Typescript app loads and tries to call the context manager method setFirstValidConnector as described in the latest 5.0.3 web3-react here
This is the full code:
./wallet/connect.ts
import { Connectors } from 'web3-react'
const { InjectedConnector } = Connectors
const metamask = new InjectedConnector({ supportedNetworks: [1, 4] })
const alchemy = new Connectors.NetworkOnlyConnector({ providerURL: "https://eth-rinkeby.alchemyapi.io/v2/..."});
export const connectors = { metamask, alchemy }
App.tsx
import React, { useEffect } from 'react';
import Web3Provider, { useWeb3Context } from 'web3-react';
import { connectors } from './wallet/connect';
export default function App() {
const context = useWeb3Context()
useEffect(() => {
context.setFirstValidConnector(['metamask', 'alchemy']) // => No <Web3Provider ...> Found.
}, [])
return (
<Web3Provider
connectors={connectors}
libraryName={'ethers.js'}
>
<div className="App">
<ButtonAppBar />
<AboutSection />
<Workspace />
</div>
</Web3Provider>
);
};
Does anyone happen to see where I'm going wrong? Thank you!

Related

TypeError: supabaseClient.auth.getSession is not a function. Error with NextJS and Supabse

I'm using supabase auth helper package to React and Next in my project. Immediately, when I start the page, I get an error message that says the following:
And it is that I am not calling that supabaseClient.auth.getSession() method. Which makes me believe that the error is internal. i'm just following the documentation: doc. And use the code that appears in the Basic Setup and in Server-side rendering (SSR)
Actually i have this:
`
// pages/_app.js
import { useState } from 'react'
import { useRouter } from 'next/router'
import '../styles/global.css'
import ProfileContext from '../utils/context/ProfileContext'
import useProfile from '../utils/hooks/useProfile'
import ProtectedRoutes from '../utils/constants/rutas/protectedRoutes'
const MyApp = ({ Component, pageProps }) => {
const [supabaseClient] = useState(() => createBrowserSupabaseClient())
console.log('supabaseClient', supabaseClient)
return (
<SessionContextProvider
supabaseClient={supabaseClient}
initialSession={pageProps.initialSession}
>
<ProfileContext.Provider value={useProfile()}>
<Component {...pageProps} />
</ProfileContext.Provider>
</SessionContextProvider>
)
}
export default MyApp
`
`
// pages/index.js
import { createServerSupabaseClient } from '#supabase/auth-helpers-nextjs'
import { useState, useEffect } from "react"
import Layout from "../layout/Layout"
import List from "../components/List"
import Empty from "../components/Empty"
import { supabase } from "../utils/supabaseClient"
const Index = ({ allData }) => {
const [session, setSession] = useState(null)
useEffect(() => {
setSession(supabase.auth.session())
}, [])
return (
<Layout>
{allData.length ? <List allData={allData} /> : <Empty />}
</Layout>
);
}
export default Index
export async function getServerSideProps(ctx) {
let { data: receptions, error } = await supabase
.from('receptions')
.select('*')
.order('id', { ascending: false })
if (error) throw error
return {
props: {
allData: receptions
},
};
}
`
As you will notice at no time I make use of the getSession() method. I hope I explained myself well.
Try this in to see if the user is not logged in to send the user to login.
This would be because you have an older version of the supabase-js library installed. Please install the latest 2.x version in order for this to work.
Run the following command to get the latest v2 version
npm install #supabase/supabase-js#2

Inserting Middleware(insights) with Instantsearch react

So, we have a functional search with Algolia/Instantsearch/React/Nextjs. But the Insights middleware is currently not setup.
Below is a trimmed version of the implementation, we use custom widgets to have more fine control over the display of results.
We use the hooks implementation for the custom widgets like so
const { hits, sendEvent, ... } = useInfiniteHits(props)
import { useState } from 'react'
import algoliasearch from 'algoliasearch/lite'
import { InstantSearch, InstantSearchSSRProvider } from 'react-instantsearch-hooks-web'
import SearchBox from '#components/swatches/algolia/SearchBox'
import Hits from '#components/swatches/algolia/Hits'
import RefinementList from '#components/swatches/algolia/RefinementList'
import CurrentRefinements from '#components/swatches/algolia/CurrentRefinements'
import { getServerState } from 'react-instantsearch-hooks-server'
import Container from 'react-bootstrap/Container'
import Row from 'react-bootstrap/Row'
import Col from 'react-bootstrap/Col'
import { history } from 'instantsearch.js/es/lib/routers/index.js'
import styles from '#styles/page.module.scss'
const Page = ({ serverState, url }) => {
const searchClient = algoliasearch(
process.env.NEXT_PUBLIC_ALGOLIA_INDEX_ID,
process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_KEY
)
return (
<div className={styles.wrapper}>
<InstantSearchSSRProvider {...serverState}>
<InstantSearch
searchClient={searchClient}
indexName={process.env.NEXT_PUBLIC_ALGOLIA_INDEX}
routing={{
router: history({
getLocation: () =>
typeof window === 'undefined' ? new URL(url) : window.location,
}),
}}
>
<Container fluid="lg">
<div className="mb-3">
<SearchBox />
</div>
<CurrentRefinements />
<Hits />
</Container>
</InstantSearch>
</InstantSearchSSRProvider>
</div>
)
}
export default Page
export async function getServerSideProps({ req, res, resolvedUrl}) {
const protocol = req.headers.referer?.split('://')[0] || 'https';
const url = `${protocol}://${req.headers.host}${req.url}`;
const serverState = await getServerState(<Page url={url} />);
return {
props: {
serverState,
url,
},
}
}
So my question is, where do we hook up the insights middleware for this specific implementation?
Reading the docs, (https://www.algolia.com/doc/api-reference/widgets/instantsearch/react-hooks/) I'm not really 100% sure where to start. I can't find anywhere in the instantsearch react docs where it references anyway to configure that sort of thing.
Am I better of just firing events at the API directly instead of with InstantSearch?
Thanks
The trick is finding the InstantSearch instance using useInstantSearch:
const instantSearch = useInstantSearch();
instantSearch.use(middleware)
The docs should tell you what to do from there.

Creating default chat groups in Sendbird using React

We've integrated a chat UI into a project using Sendbird. The chat interface is now working and what I am trying to do now is implement a feature where there are 2 default chat groups as shown in the mockup below:
I have already gone through the docs but I can’t seem to find the information I need to implement this feature. Can this be implemented? can someone guide me to the right direction, please?
import React, { useEffect, useState, useRef } from 'react';
import { useHistory } from 'react-router-dom';
import { useSelector } from 'react-redux';
import 'sendbird-uikit/dist/index.css';
import { App as SendBirdApp, } from 'sendbird-uikit';
import { getModuleState as getAuthModuleState } from 'services/auth';
import colorSet from './styled/chatPalette';
import { Chat, ChatContainer, List } from './styled/chatPage';
import ChatGroups from './ChatGroups';
function ChatPage(props) {
const { theme } = props;
const history = useHistory();
const authState = useSelector(getAuthModuleState);
const userId = authState.username;
const nickname = authState.username;
const appId = authState.sendbirdData.appId;
const accessToken = authState.sendbirdData.accessToken;
useEffect(() => {
if (!userId || !nickname) {
console.error('Error, empty userId or nickname');
}
}, [userId, nickname, history]);
return (
<ChatContainer>
<SendBirdApp
appId={appId}
userId={userId}
nickname={nickname}
colorSet={colorSet}
/>
</ChatContainer>
);
}
export default ChatPage;
you can use the <SendbirdProvider> component and provide your custom channel preview component (let's say <ChannelPreview>) inside the <ChannelList> component.
Within your custom preview component (<ChannelPreview>) you can choose wether or not to show a specific channel based on its member count (channel.memberCount) as shown below:
import { Channel, ChannelList, SendBirdProvider } from 'sendbird-uikit';
import 'sendbird-uikit/dist/index.css';
import { useState } from 'react';
const CHANNEL_PREVIEW_MODES = [
'1-on-1',
'Group'
]
function ChannelPreview({channel, previewMode}) {
if (
(channel.memberCount <=2 && previewMode !== CHANNEL_PREVIEW_MODES[0]) ||
(channel.memberCount > 2 && previewMode !== CHANNEL_PREVIEW_MODES[1])
) {
return null
}
return (
<div key={channel.url}>
<img height="20px" width="20px" src={channel.coverUrl}/>
{channel.url}
</div>
)
}
function App() {
const [previewMode, setPreviewMode] = useState(CHANNEL_PREVIEW_MODES[0])
const [currentChannel, setCurrentChannel] = useState(null);
return (
<div className="App">
<SendBirdProvider
userId='<USER_ID>'
appId='<APP_ID>'
>
<div>
{CHANNEL_PREVIEW_MODES.map(mode =>
<label className="preview-mode-radio">{mode}
<input
type='radio'
value={mode}
name='preview-mode'
onChange={() => setPreviewMode(mode)}
checked={previewMode === mode}
/>
</label>
)}
</div>
<ChannelList
renderChannelPreview={({channel}) => <ChannelPreview channel={channel} previewMode={previewMode} />}
onChannelSelect={channel => setCurrentChannel(channel)}
/>
<Channel channelUrl={currentChannel?.url} />
</SendBirdProvider>
</div>
);
}
export default App;

How to test code that uses a custom hook based on useContext with react-testing-library and jest

I've created a custom context hook - and I'm struggling to figure out how to pass values to its provider during testing.
My hook:
import React, { createContext, useContext, useState } from 'react';
const Context = createContext({});
export const ConfigurationProvider = ({ children }) => {
// Use State to keep the values
const [configuration, setConfiguration] = useState({});
// pass the value in provider and return
return (
<Context.Provider
value={{
configuration,
setConfiguration,
}}
>
{children}
</Context.Provider>
);
};
export const useConfigurationContext = () => useContext(Context);
export const { Consumer: ConfigurationConsumer } = Context;
This is how it's used in the application:
function App() {
return (
<ConfigurationProvider>
<div className="app">
<ComponentA />
</div>
</ConfigurationProvider>
);
}
And in ComponentA:
const ComponentA = () => {
// Get configuration
const configuration = useConfigurationContext();
return (
<div>{JSON.stringify(configuration)}</div>
)
}
This all works fine - considered that I'm calling setConfiguration from another component and set an object. Now for the testing part:
import React, { Component, createContext } from 'react';
import { render, waitFor } from '#testing-library/react';
import ComponentA from 'componentA';
const config = {
propertyA: 'hello',
};
test('renders the config', async () => {
const ConfigurationContext = createContext();
const { queryByText } = render(
<ConfigurationContext.Provider value={config}>
<ComponentA />
</ConfigurationContext.Provider>
);
expect(queryByText('hello')).toBeInTheDocument();
});
This doesn't work - I'm expecting the value that I'm sending in would be rendered in the div, but the context is an empty object. What am I doing wrong?
Thanks to Carle B. Navy I got the reason why it doesn't work. For other people two wonder what the solution is I fixed it by doing the following:
In my context hook, I changed the last line to export the provider as well:
export const { Consumer: ConfigConsumer, Provider: ConfigProvider } = Context;
Then in my test case, instead of creating a new context, I import the ConfigProvider at the top, and then:
const { queryByText } = render(
<ConfigProvider value={config}>
<ComponentA />
</ConfigProvider>
);
Thanks for helping me solve this and hope this helps someone else.

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 };

Resources