TypeError: Cannot read properties of undefined (reading 'Contract') - Next.js, web3.0 - reactjs

I'm trying to create a small web3.0 app, using next.js.
I have deployed my contract on rinkeby test network, and I am able to check the functionalities using Remix, work properly. I have also worked on similar projects on react, they also work as exepected.
But when I try to connect I am currently facing the following issue (maybe this has something to do with Server side rendering of next.js or HttpProvider, I'm not sure):
TypeError: Cannot read properties of undefined (reading 'Contract')
3 | import address from './build/campaignHubAddress.json';
4 |
> 5 | const instance = new web3.eth.Contract(contract.abi, address.campaignHubAddress);
| ^
6 | export default instance;
web3.js
import Web3 from 'web3';
let web3;
if (typeof window !== 'undefined' && typeof window.ethereum !== 'undefined') {
window.ethereum.request({ method: "eth_requestAccounts" });
web3 = new Web3(window.ethereum);
} else {
const provider = new Web3.providers.HttpProvider(
'https://rinkeby.infura.io/v3/3ed112ee6c4d42a09e485ddb5eec5fa2'
);
web3 = new Web3(provider);
}
export default web3;
instance.js
import web3 from 'web3';
import contract from './build/CampaignHub.json';
import address from './build/campaignHubAddress.json';
const instance = new web3.eth.Contract(contract.abi, address.campaignHubAddress);
export default instance;
index.js
import React from 'react';
import web3 from '../web3';
import instance from '../instance';
class Index extends React.Component{
static async getInitialProps(){
const campaigns = await instance.methods.getCampaigns().call();
return { campaigns };
}
render() {
return (
<>
<p>Hello, this is the test page for now.</p>
<p>Web3 version: {web3.version}</p>
<p>List of all the running campaigns: {this.props.campaigns} </p>
</>
);
}
}
export default Index;
This seems basic, but I have been stuck at it for some time now.

You already create instance of your web3 in web3.js
you can use it directly without using the "new"
import web3 from 'web3';
import contract from './build/CampaignHub.json';
import address from './build/campaignHubAddress.json';
const instance = web3.eth.Contract(contract.abi, address.campaignHubAddress);
export default instance;

After scratching a lot of head, I found that the error was in instance.js. While importing import web3 from 'web3'; I should have done import web3 from './web3';

Related

Error when navigating to `/blog` in next.js project

The Problem:
I'm building a blog with Next and sanity. When navigating to /blog, i'm encountering this error in the browser:
./sanity.js:2:0
Module not found: Can't resolve '#sanity/image-url'
1 | import { createCurrentUserHook, createClient } from "next-sanity";
> 2 | import imageUrlBuilder from "#sanity/image-url";
3 |
4 | export const config = {
5 | // Find your project ID and dataset in 'sanity.json' in your studio project.
Import trace for requested module:
./pages/blog.tsx
https://nextjs.org/docs/messages/module-not-found
The folder structure is:
root
-> components
-> pages
-> post
-> [slug].tsx
-> index.tsx
-> blog.tsx
-> sanity subfolder
-> public
-> styles
sanity.js (config file)
The sanity config file
I have a sanity config file, which exports some helper functions. One of which, is the imageUrlBuilder function, which i'm assuming the error is coming from. Here is my sanity config file: Note: this is pulled from sanity docs.
import { createCurrentUserHook, createClient } from "next-sanity";
import imageUrlBuilder from "#sanity/image-url";
export const config = {
// config info here
};
// Set up the client for fetching data in the getProps page functions.
export const sanityClient = createClient(config);
// Builder function to combo with urlFor function.
const builder = imageUrlBuilder(sanityClient);
// Helper function to generate urls from sanity photos.
export const urlFor = (source) => {
return builder.image(source);
};
The helper function was working in a previous version, and was able to pull images from sanity and display in the document. But i'm unsure why it's causing issues with page routing.
The blog page component:
import React from "react";
import BlogPreview from "../components/BlogPreview";
import { getAllPosts } from "../queries";
import { sanityClient } from "../sanity";
import { Post } from "../typings";
interface Props {
posts: [Post];
}
// required for server-side rendering. returns 'props' object from db.
export const getServerSideProps = async () => {
let query = getAllPosts;
const posts = await sanityClient.fetch(query);
return {
props: {
posts,
},
};
};
function blog({ posts }: Props) {
return (
<div>
<div className='md:grid md:grid-cols-2'>
{posts.map((post) => {
return (
<BlogPreview
key={post._id}
title={post.title}
description={post.description}
mainImage={post.mainImage}
slug={post.slug}
/>
);
})}
</div>
</div>
);
}
export default blog;
I've tried:
Logging sanity data to the console to check for config errors.
Googling the error: Module not found: Can't resolve '#sanity/image-url'
Conclusion
I'm unsure what the issue is, and how I can potentially solve it. Would love some ideas.
Thanks in advance
It sounds like you don't have the #sanity/image-url module installed in your project.
Run this in your project directory and you should be good to go!
npm install --save #sanity/image-url

How to fix this bug ? Unexpected SyntaxError: Unexpected token '!'

So basically the console is showing me that I have an unexpected token but I don't think there is any unexpected token. Please help me. I have taken way too much time trying to fix this problem. Here is the code -
import React from 'react';
import firebase from 'firebase';
export default function App() {
// I have deleted this information because I don't want anyone to access my data
const firebaseConfig = {};
firebase.initializeApp(firebaseConfig);
function signInWithGoogle() {
var google_provider = new firebase.auth.GoogleAuthProvider();
firebase
.auth()
.signInWithPopup(google_provider)
.then((res) => {
console.log(res);
})
.catch((error) => {
console.log(error);
});
}
return (
<div>
<h1>Google Sign In Authentication</h1>
<button onClick={signInWithGoogle}>Sign In</button>
</div>
);
}
The only issue I see in the provided code is you have not imported the Firebase Auth SDK. You can import that as shown below:
import firebase from 'firebase';
import "firebase/auth"
Also make sure you are using V8.X.X or lower with above code. If you have new Modular SDK V9.0.0+ then change your imports to compat version to keep using existing code:
import firebase from 'firebase/compat/app';
import "firebase/compat/auth"

I'm trying to solve a React syntax ERROR, but nothing is working

My App.js code is reciving the error: ./src/App.js SyntaxError: C:\Users\gabri\Desktop\bd\src\App.js: Unexpected token, expected "," (19:15) 17 | return ( 18 | // variavel - componente > 19 | {character ? : P ```
import './App.css';
import {useState} from 'react';
import characterCard from './components/characterCard';
function App() {
const [character, setCharacter] = useState ({});
const [name, setName] = useState ('Walter+White');
async function getCharacter(){
const [character] = await (await fetch(`https://www.breakingbadapi.com/api/characters?name=${name}`)).json();
console.log(character);
setName(character);
}
return (
{character ? <characterCard character = {character}/> : <button onClick = {getCharacter}>Procurar personagem</button>}
)
};
export default App;
And i have here my index.js
function characterCard({character}){
return (<h1>{character.name}</h1>);
}
export default characterCard;
SOMEONE COULD HELP ME PLEASE?
In order to use React syntax (XML in JS), you have to have 'React' imported in every component using the syntax:
import React from 'react';
In your case, since you're also importing useState(), modify the import statement to:
import React, {useState} from 'react';
This would work granted that you've configured your project to use Babel. If you're new to all this and just want to get started with learning React, try create-react-app.

Authentication with Firebase and Cloud Firestore

I am trying to figure out how to add authentication to a react app that uses Cloud Firestore rather than Realtime Database.
I followed this tutorial and got the whole thing working. Then - the change I'm trying to add is the move from Realtime Database to Cloud Firestore - this makes a difference to whether authentication works. I have made 20 new projects to try to get this work - totally without the process in the tutorial and just relying on firebase documentation. None of them work.
Currently, I have a config file with:
import app from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
import firestore from "firebase/firestore";
class Firebase {
constructor() {
app.initializeApp(config).firestore();
this.auth = app.default.auth();
// this.db = app.firebase.database()
this.db = app.firestore();
}
Then, i have a form with this submit handler:
import Firebase from '../../../firebase.1';
handleCreate = () => {
const { form } = this.formRef.props;
form.validateFields((err, values) => {
if (err) {
return;
};
const payload = {
// ...values,
name: values.name,
email: values.email,
organisation: values.organisation,
beta: values.beta,
role: values.role,
// createdAt: Firebase.FieldValue.serverTimestamp()
}
console.log("formvalues", payload);
Firebase
.auth()
.createUserWithEmailAndPassword(values.email, values.password)
console.log('Received values of form: ', values);
Firebase
.collection("users")
.add(payload)
// .then(docRef => {
// resetForm(initialValues);
// })
.then(e => this.setState({ modalShow: true }))
form.resetFields();
this.setState({ visible: false });
this.props.history.push(DASHBOARD);
});
};
At the moment, when I console.log(Firebase) I get:
Uncaught ReferenceError: Firebase is not defined
I have seen this post and followed each one of the recommendations in all of the answers.
I have tried changing the config file uses:
this.auth = app.default.auth();
It makes no difference.
When I try to use this, i get an error that says:
TypeError: _firebase_1__WEBPACK_IMPORTED_MODULE_14__.default.auth is not a function
Does anyone know how to use auth with firebase - where there is a Cloud Firestore instead of a Realtime Database - it's so weird that this makes a difference to whether the authentication tool works.
I've turned off the timestamp entry because I can't get firestore to record that either - but that is a problem for another day. I'm really trying to figure out how to use the authentication tool for now.
NEXT ATTEMPT
I tried to change the firebase.js file so that the config now looks like this:
import app from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
const devConfig = {
};
const prodConfig = {
};
const config =
process.env.NODE_ENV === 'production' ? prodConfig : devConfig;
const Firebase = app.initializeApp(config);
const database = app.firestore();
const auth = app.auth();
const settings = { timestampsInSnapshots: true };
export { Firebase, database as default, settings, auth };
Now, I get an error that says:
TypeError: _components_firebase__WEBPACK_IMPORTED_MODULE_2__.default
is not a constructor
I have been googling - what is a constructor. What is a webpack imported module number reference etc for the last few hours. I would love to know how to translate these error messages into something understandable.
Googling this exact error message suggests that something is wrong with the way the import and export statements are made. The new export in firebase.js is unusual (but others on Stack Overflow have tried it with problems using Firebase). It's still a question mark for me because I don't understand what the error message means.
The error message points to this line of my src/index.js
ReactDOM.render(
<FirebaseContext.Provider value={new Firebase()}>
That line comes from:
import FirebaseContext, { withFirebase } from './Context';
import Firebase from '../../firebase.1';
export default Firebase;
export { FirebaseContext, withFirebase };
That file imports from:
import React from 'react';
const FirebaseContext = React.createContext(null);
export const withFirebase = Component => props => (
<FirebaseContext.Consumer>
{firebase => <Component {...props} firebase={firebase} />}
</FirebaseContext.Consumer>
);
export default FirebaseContext;
It would be a huge reveal if anyone has any advice for learning how to learn what error messages mean. For the moment I'm guessing.
I just finished the tutorial recently also, but I simplified my firebase file. I export only the reference to the initialised firebase
import app from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
const config = {
//...
};
const firebase = app.initializeApp(config);
export default firebase;
And in my project I have:
//...
import firebase from '../../firebase';
//...
useEffect(() => {
const listener = firebase
.firestore()
.collection(COLLECTIONS.USERS)
.onSnapshot(querySnapshot => {
setUsers(querySnapshot);
querySnapshot.forEach(doc => console.log(doc.id, doc.data()));
});
return listener;
}, []);
//...
Check out my Github project here -> https://github.com/henev/react-auth-with-firebase

Integrating web3 from Metamask in React

I am new to ReactJS.
Seem to be having trouble integrating web3 from Metamask in React.
Metamask version: web3#1.0.0-beta.34
import Web3 from 'web3'
let web3;
window.addEventListener('load', function () {
if (typeof window.web3 !== 'undefined') {
web3 = new Web3(window.web3.currentProvider);
} else {
// No web 3 provider
console.log("Please install Metamask");
}
});
export default web3;
Getting the following error:
window is not defined
ReferenceError: window is not defined
at Object../lib/getWeb3.js (lib/getWeb3.js:5:0)
window is not defined on Server, only in client's browser, hence you can't use MetaMask server-side. However, you can connect to INFURA when you want to use web3 in your React component server-side or without MetaMask support.
The simplest way is to use react-web3-provider component.
Add the Web3Provider to your root React component:
import Web3Provider from 'react-web3-provider';
ReactDOM.render(
<Web3Provider
defaultWeb3Provider="https://mainnet.infura.io/YOUR_API_KEY"
loading="Loading..."
>
<App />
</Web3Provider>
)
Then in component where you want to use Web3:
import { withWeb3 } from 'react-web3-provider';
class MyComponent {
render() {
const { web3 } = this.props;
web3.eth.getAccounts(console.log);
// Version 1.0.0-beta.35
return "Web3 version: {web3.version}";
}
}
export default withWeb3(MyComponent);

Resources