web3 react contract interaction - reactjs

I am having some issues when calling a contract via form with React and Web3 component.
In my contract, I have a public function called GetDomainInfo which takes the domain as a parameter. You can view the contract here: https://ropsten.etherscan.io/address/0x756ad7f7c22e7c04a845bd8a138e455a1bc95f6f
The problem is that my components gets the form value, but when use it in a contract, gives the error:
Uncaught TypeError: Cannot read property 'GetDomainInfo' of undefined
Code:
GetInfo = (event) => {
event.preventDefault();
console.log(this.state.value);
const response = this.state.rouDomains.method.GetDomainInfo(this.state.value).send({from: this.state.account})
.once('receipt', (receipt) => {
console.log("receipt: ", receipt);
console.log(response);
})
}
The data arrives in console.log(this.state.value), I can see it.
EDIT: rouDomains is the async load data from web3.
async loadData() {
const web3 = new Web3(Web3.givenProvider || "http://localhost:8545");
const network = await web3.eth.net.getNetworkType();
this.setState({network});
//Fetch account
const accounts = await web3.eth.getAccounts();
this.setState({ account: accounts[0]});
//Load the contract
const rouDomains = new web3.eth.Contract(ROU_TLD, ROU_TLD_ADDRESS);
this.setState({ rouDomains });
console.log("ROU: ", rouDomains);
}

The answer was that I forgot a 's' for method in the below:
const response = this.state.rouDomains.method.GetDomainInfo(this.state.value).send({from: this.state.account})
const response = this.state.rouDomains.methods.GetDomainInfo(this.state.value).send({from: this.state.account})
Stupid rookie mistake :)

Related

How to use API Route in next js?

I am learning how to design API and at the same time how to use next.js API route.
I have set my first route api/property/[propertyId] that returns the specific property detail.
Now I am trying to set a dynamic route for the specific property id in the page folder page/property/[propertyId]. My issue is when I am getting directed on the specific page the data is not there as expected. I am receiving a response for error message.
Can someone point out what I did wrong, please?
pages>api>property>[propertyId]
export default function propertyHandler ({query : {propertyId} } ,res) {
var parser = new xml2js.Parser({explicitArray : false});
const data = fs.readFileSync(path.join(process.cwd(),'listing.xml'))
parser.parseString(data,function (err, results){
results = results.client.secondhandListing.property
const filteredProp = results.filter((property) => property.id === propertyId)
filteredProp.length > 0 ? res.status(200).json(filteredProp[0]) : res.status(404).json({message: `Property with id: ${propertyId} not found.` })
})
}
pages>property>[id].js
export const getDetails = async() => {
const res = await fetch(`${baseUrl}/api/property/[property.Id]}`)
const data = res.json()
return data
}
export async function getServerSideProps({params: { id } }) {
const data = await getDetails(`${baseUrl}/api/property/${id}`)
return {
props: {
propertyDetails: data
}
}
}
I got the answer to my mistake from somewhere else. It was my getdetails function that was wrong.
I have amended it to:
export const getDetails = async(baseUrl)=>{
const res = await fetch(baseUrl)
const data = await res.json()
return data
};
and it worked.

React Firebase, Await data before do code

I get this error with a function in react. How can I make sure the I received the data before i use .push?
Unhandled Rejection (TypeError): Cannot read property 'push' of null
const joinTheLobby = () => {
if(lobbyKey != ''){
// Add Player to DB Lobby.
const db = firebase.database().ref(`Lobby/${lobbyKey}/players`);
let allPlayers = [];
let pushPlayers = [];
let newPlayer = {'userName': userName};
db.on('value', async (snapshot) => {
allPlayers = await snapshot.val();
allPlayers.push(newPlayer);
allPlayers.map(({userName}) => {
pushPlayers.push(userName);
});
});
This is how I fire the function. Also, Will this function run immediately after state updates?
<button onClick={joinTheLobby}>Join</button>
Looking at this code, snapshot.val() is most likely returning null.
null is a valid thing for it to return according to the docs: https://firebase.google.com/docs/reference/node/firebase.database.DataSnapshot#val
So, most likely this Lobby/${lobbyKey}/players does not exist in Firebase.

Internal Error when creating new user with Firebase Auth in React

I am working with Firebase for authentication in my application, and below is the function I am calling on my form. Before I had added the .then() with the updateProfile inside, it was working fine. However, now when I create a new user, the user's email and password is stored, but I get the error Internal error: Too much recursion and the displayName is never set.
const handleSignUp = useCallback(
async (event) => {
event.preventDefault();
const { fullName, email, password } = event.target.elements;
try {
await app
.auth()
.createUserWithEmailAndPassword(email.value, password.value)
.then((result) => {
const user = app.auth().currentUser;
return user.updateProfile({
displayName: fullName,
});
});
} catch (error) {
alert(error);
}
history.push("/dashboard");
},
[history]
);
I've tried different ways of calling updateProfile (using the function argument & the user variable as in the example below. I am still getting this error.
Is there a way to write this code to avoid that recursion error?
First, I suggest you to choose between using async/await or then to handle promises.
Second, you can use createUserWithEmailAndPassword return value, as such:
const userCredentials = await app.auth().createUserWithEmailAndPassword(email.value, password.value);
const user = userCredentials.user;
await user.updateProfile({ displayName: fullName });
The relevant documentation: https://firebase.google.com/docs/reference/js/firebase.auth.Auth#createuserwithemailandpassword

Login status in React

I created authorization in javascript. Then if success login I redirect to React project with url parameter http://localhost:3000/?phoneNum=%2B77072050399
Then in React I get userId by using the passed url parameter => phoneNumber using axios.
I realized it in App.js. Code below:
let url = window.location.href;
let params = (new URL(url)).searchParams;
const userPhoneNum = encodeURIComponent(params.get('phoneNum'));
const [userToken, setUserToken] = useState(null);
const getUserToken = async() => {
try {
const data = await axios
.get(`https://stormy-escarpment-89406.herokuapp.com/users/getToken?phone_number=${userPhoneNum}`)
.then(response => {
setUserToken(response.data);
})
.catch(function(error) {
console.log('No such user! Error in getting token!');
});
} catch (e) {
console.log(e);
}
}
useEffect(() => {
getUserToken();
console.log(userToken);
}, userToken);
So, when I go to next page localhost:3000/places, it is requesting for userToken again with parameter null, because there is no param phoneNum.
How to make it to request only one time and save the userId after it is taken in main page. So, then only when I click LogOut button reset the variable where userID is saved.
If you want to do that without using any third party libraries you can use browser's in built storage api
So, when you receive the token, you can store that in the local storage of the browser using localstorage.setItem and later when you wan to see if the token is there or not just read from there using localStorage.getItem
const getUserToken = async() => {
try {
const data = await axios
.get(`https://stormy-escarpment-89406.herokuapp.com/users/getToken?phone_number=${userPhoneNum}`)
.then(response => {
setUserToken(response.data);
Storage.setItem('token',JSON.stringify(response.data))
})
.catch(function(error) {
console.log('No such user! Error in getting token!');
});
} catch (e) {
console.log(e);
}
}
For Logout you can simply remove the token using localStorage.removeItem
You can easily achieve this by using the react-cookie library
npm i react-cookie
Can be easily implemented in your code by
cookies.set('key', value, { path: '/' });
cookies.get('key')
After getting the userNumber form the param
const userPhoneNum = encodeURIComponent(params.get('phoneNum'));
cookies.set('userphoneNum', userPhoneNum);
View the documentation for more information
https://www.npmjs.com/package/react-cookie

ReactJS: Unable to parse through a 2d array outside async function

Trying to setState of an array in an async function, and accessing it inside the async function works fine. But when I try to access it outside the async function it only parses through the first layer meaning bookDetails[0], while parsing for bookDetails[0][0] gives an error as "cannot-read-property-0-of-undefined"
getAll = async () => {
const { contract } = this.state;
const response = await contract.methods.getBooks().call();
this.setState({ bookDetails: response});
console.log("books: ",this.state.bookDetails[0][0]);
};
//OUTPUT=> books: nanme
//console.log outside the async function gives error
notice that setState is not sync itself, you have to check the updated state in its callback:
getAll = async () => {
const { contract } = this.state;
const response = await contract.methods.getBooks().call();
this.setState({ bookDetails: response}, () => console.log("books: ",this.state.bookDetails[0][0]);
);};
Other than that, the snippet is not enough to verify why outsile async function you can't log correctly. Please provide a more complete snippet.

Resources