In ReactJs it works well.
import React, { useState, useEffect } from "react";
import { Snackbar } from "#material-ui/core";
import axios from "axios";
import { withTranslation } from "../../i18n";
import MuiAlert from "#material-ui/lab/Alert";
import sha512 from "crypto-js/sha512";
import { LoginEmailIn, LoginEmailOut } from "../../Types";
import { getTempUserUuid } from "../../util/Utility";
//import ReactPixel from "react-facebook-pixel";
import styles from "../../styles/LoginAndRegistration.module.css";
import {BEUrl} from "../../util/Utility"
function Alert(props: any) {
return <MuiAlert elevation={6} variant="filled" {...props} />;
}
function LoginWithEmail({ t },props: {
eventId: string;
trackUserInteractions:boolean;
eventName: string;
setLogin: (a:boolean)=> void;
}) {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [alertOpen, setAlertOpen] = useState(false);
const [alertMessage, setAlertMessage] = useState("");
const [alertType, setAlertType] = useState("error");
const alertClose = (event: any, reason: any) => {
if (reason === "clickaway") {
return;
}
setAlertOpen(false);
};
const checkEmail = () => {
const regex = /^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
if (email === "") {
setAlertType("error");
setAlertMessage(t("Please enter your registered e-mail address"));
setAlertOpen(true);
return false;
} else if (!regex.test(email)) {
setAlertType("error");
setAlertMessage(t("The entered e-mail address is not valid"));
setAlertOpen(true);
return false;
} else return true;
};
const checkPassword = () => {
if (password === "") {
setAlertType("error");
setAlertMessage(t("Please enter your password"));
setAlertOpen(true);
return false;
} else return true;
};
const loginButtonPressed = () => {
if (checkEmail() && checkPassword()) {
const loginData: LoginEmailIn = {
email: email,
passwordHash: sha512(password).toString(),
tempUserId: getTempUserUuid(),
};
let url = BEUrl + "loginEmail";
axios({
method: "post",
url: url,
data: loginData,
headers: { "Content-Type": "application/json", crossDomain: true },
})
.then((resp: any) => {
const data: LoginEmailOut = resp.data;
if (!data.error) {
setAlertType("success");
setAlertMessage(t(`Successful login, Welcome ${data.userName!}`));
setAlertOpen(true);
localStorage.setItem("isRegistrationHappened", "true");
localStorage.setItem("userNameLoggedIn", data.userName!);
localStorage.setItem("jwt", data.jwt!);
setTimeout(function () {
window.location.reload();
}, 1200);
} else {
setAlertType("error");
setAlertMessage(t(`${data.error}`));
setAlertOpen(true);
}
})
.catch((error) => console.error(error));
}
};
/*const trackEmailLoginFinished = () => {
if (useClientSide) {
if (
window.location.hostname !== "localhost" &&
props.trackUserInteractions &&
!userInteractions.includes(`IA ${props.eventName} EmailLoginFinished`)
) {
ReactPixel.track(`IA ${props.eventName} EmailLoginFinished`, {
content_ids: [props.eventId],
});
userInteractions.push(`IA ${props.eventName} EmailLoginFinished`);
localStorage.setItem(
"userInteractions",
JSON.stringify([...userInteractions])
);
}
}
};*/
const [userInteractions, setUserInteractions] = useState();
useEffect(()=> {
setUserInteractions(JSON.parse(
localStorage.getItem("userInteractions") ?? "[]"
))
},[])
return (
<>
<div className={styles.loginContainer}>
<label className={styles.loginInputLabel}>{`${t(
"Please enter your e-mail address"
)}`}</label>
<input
id="loginMail"
name="loginMail"
className="loginInput toLowerCase"
autoFocus
type="email"
onChange={(event) => setEmail(event.target.value.toLowerCase())}
/>
</div>
<label className="loginInputLabel">{`${t(
"Please enter your password"
)}`}</label>
<input
id="loginPassword"
className="loginInput"
name="loginPassword"
type="password"
onChange={(event) => setPassword(event.target.value)}
/>
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
flexDirection: "column",
}}
>
<button
className="loginAndRegButton"
onClick={() => {
loginButtonPressed();
/*trackEmailLoginFinished();*/
}}
>
{t("Login")}
</button>
<p style={{ margin: 0 }} className="loginOrRegSwitch">
{t("You don't have an account yet")}?{" "}
<a href="#" onClick={() => props.setLogin(false)}>
{" "}
{t("Sign up")}
</a>
</p>
</div>
<Snackbar open={alertOpen} autoHideDuration={3000} onClose={alertClose}>
<Alert onClose={alertClose} severity={alertType}>
{alertMessage}
</Alert>
</Snackbar>
</>
);
}
export default withTranslation("translate")<any>(LoginWithEmail);
I think it has to be:
function LoginWithEmail({ t, ...props }) { /* ... */ }
Related
Good morning. I am trying to integrate PayPal check out in my React app. Everything works fine except that the Paypal Checkout amount is not showing the same as the total cart amount. Checkout amount is fixed at $0.01 and not changing as cart amount changes. Please what could i be doing wrong ??? This is the code
#cart.js code
import React, { useContext, useState, useEffect } from "react";
import { GlobalState } from "../../../GlobalState";
import axios from "axios";
import PayPalButton from "./PaypalButton";
function Cart() {
const state = useContext(GlobalState);
const [cart, setCart] = state.userAPI.cart;
const [token] = state.token;
const [total, setTotal] = useState(0);
useEffect(() => {
const getTotal = () => {
const total = cart.reduce((prev, item) => {
return prev + item.price * item.quantity;
}, 0);
setTotal(total);
};
getTotal();
}, [cart]);
const addToCart = async () => {
await axios.patch(
"/user/addcart",
{ cart },
{
headers: { Authorization: token },
}
);
};
const increment = (id) => {
cart.forEach((item) => {
if (item._id === id) {
item.quantity += 1;
}
});
setCart([...cart]);
addToCart();
};
const decrement = (id) => {
cart.forEach((item) => {
if (item._id === id) {
item.quantity === 1 ? (item.quantity = 1) : (item.quantity -= 1);
}
});
setCart([...cart]);
addToCart();
};
const removeProduct = (id) => {
if (window.confirm("Do you want to delete this product?")) {
cart.forEach((item, index) => {
if (item._id === id) {
cart.splice(index, 1);
}
});
setCart([...cart]);
addToCart();
}
};
const tranSuccess = async (payment) => {
console.log(payment);
};
if (cart.length === 0)
return (
<h2 style={{ textAlign: "center", fontSize: "5rem" }}>Cart Empty</h2>
);
return (
<div>
{cart.map((product) => (
<div className="detail cart" key={product._id}>
<img src={product.images.url} alt="" />
<div className="box-detail">
<h2>{product.title}</h2>
<h3>${product.price * product.quantity}</h3>
<p>{product.description}</p>
<p>{product.content}</p>
<div className="amount">
<button onClick={() => decrement(product._id)}> - </button>
<span>{product.quantity}</span>
<button onClick={() => increment(product._id)}> + </button>
</div>
<div className="delete" onClick={() => removeProduct(product._id)}>
X
</div>
</div>
</div>
))}
<div className="total">
<h3>Total: $ {total}</h3>
<PayPalButton total={total} tranSuccess={tranSuccess} />
</div>
</div>
);
}
export default Cart;
PayPal button code
import React from "react";
import { PayPalScriptProvider, PayPalButtons } from "#paypal/react-paypal-js";
export default class PayPalButton extends React.Component {
render() {
const onSuccess = (payment) => {
console.log("The payment was succeeded!", payment);
this.props.tranSuccess(payment);
};
const onCancel = (data) => {
console.log("The payment was cancelled!", data);
};
const onError = (err) => {
console.log("Error!", err);
};
let env = "sandbox"; // you can set here to 'production' for production
let total = this.props.total;
let currency = "USD";
const client = {
sandbox:
"ARhnfWu_QrcGQa-PdvaY1RVriEmqGiSkfEWf-plauZQpQN_gyxaLjH9RXOhdQw7fxxxxxxxxxxxx",
production: "YOUR-PRODUCTION-APP-ID",
};
let style = {
size: "small",
color: "blue",
shape: "rect",
label: "checkout",
tagline: false,
};
return (
<PayPalScriptProvider
options={{
"client-id": "ARhnfWu_QrcGQa-PdvaY1RVriEmqGiSkfEWf-plauZQpQN_gyxaLjH9RXOhdQw7fxxxxxxxxxxxx",
}}
>
<PayPalButtons
env={env}
client={client}
commit={true}
total={total}
currency={currency}
onError={onError}
onSuccess={onSuccess}
onCancel={onCancel}
style={style}
/>
</PayPalScriptProvider>
);
}
}
I don't see a createOrder function anywhere. You need one, and it needs to invoke actions.order.create() with a JSON object that uses your total to set the amount.
See examples in the react-paypal-js storybook.
My code keeps bringing torusPlugin is assigned a value but never used, LoggedInView is assigned a value but never used and I don't know where I went wrong. I have checked the code and the torusPlugin function was used, same with the loggedInView.
import { useEffect, useState } from "react";
import { Card, Form } from "react-bootstrap";
import { FaComment, FaRecycle, FaRetweet, FaThumbsUp } from "react-icons/fa";
import { Web3AuthCore } from "#web3auth/core";
import {
WALLET_ADAPTERS,
CHAIN_NAMESPACES,
SafeEventEmitterProvider,
} from "#web3auth/base";
import { OpenloginAdapter } from "#web3auth/openlogin-adapter";
import { TorusWalletConnectorPlugin } from "#web3auth/torus-wallet-connector-plugin";
import Twitter from "./twitter";
import RPC from "./evm";
import { APP_CONSTANTS } from "./constants";
import "./App.css";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
const clientId = APP_CONSTANTS.CLIENT_ID; // get from https://dashboard.web3auth.io
function App() {
const [web3auth, setWeb3auth] = useState<Web3AuthCore | null>(null);
const [provider, setProvider] = useState<SafeEventEmitterProvider | null>(
null
);
const [tweets, setTweets] = useState<Array<any> | null>(null);
const [comment, setComment] = useState<string | "">("");
const [userName, setUserName] = useState<string | "">("");
const [profileImage, setProfileImage] = useState<string | "">("");
const [newTweetName, setNewTweetName] = useState<string | "">("");
const [newTweetDescription, setNewTweetDescription] = useState<string | "">(
""
);
const refreshTime = APP_CONSTANTS.REACT_APP_REFRESH_TIMER * 1000
const [torusPlugin, setTorusPlugin] =
useState<TorusWalletConnectorPlugin | null>(null);
useEffect(() => {
const init = async () => {
try {
const web3auth = new Web3AuthCore({
clientId,
chainConfig: {
chainNamespace: CHAIN_NAMESPACES.EIP155,
chainId: "0x13881",
rpcTarget: APP_CONSTANTS.RPC_TARGET, // This is the mainnet RPC we have added, please pass on your own endpoint while creating an app
},
});
const openloginAdapter = new OpenloginAdapter({
adapterSettings: {
clientId,
network: "testnet",
uxMode: "popup",
whiteLabel: {
name: "Twitter DApp",
logoLight: APP_CONSTANTS.APP_LOGO,
logoDark: APP_CONSTANTS.APP_LOGO,
defaultLanguage: "en",
dark: true, // whether to enable dark mode. defaultValue: false
},
loginConfig: {
// Add login configs corresponding to the providers on modal
// Twitter login
jwt: {
name: "Custom Auth Login",
verifier: APP_CONSTANTS.ADAPTER_TWITTER_CLIENT_VERIFIER, // Please create a verifier on the developer dashboard and pass the name here
typeOfLogin: "twitter", // Pass on the login provider of the verifier you've created
clientId: APP_CONSTANTS.ADAPTER_TWITTER_CLIENT_ID, // Pass on the clientId of the login provider here - Please note this differs from the Web3Auth ClientID. This is the JWT Client ID
},
// Add other login providers here
},
},
});
const torusPlugin = new TorusWalletConnectorPlugin({
torusWalletOpts: {},
walletInitOptions: {
whiteLabel: {
theme: { isDark: true, colors: { primary: "#ffffff" } },
logoDark:
"https://i.ibb.co/kDNCfC9/reshot-icon-wallet-9-H3-QMSDLFR.png",
logoLight:
"https://i.ibb.co/kDNCfC9/reshot-icon-wallet-9-H3-QMSDLFR.png",
},
useWalletConnect: true,
enableLogging: true,
},
});
await web3auth.addPlugin(torusPlugin);
setTorusPlugin(torusPlugin);
await web3auth.configureAdapter(openloginAdapter);
setWeb3auth(web3auth);
await web3auth.init();
if (web3auth.provider) {
await setProvider(web3auth.provider);
let user = await web3auth.getUserInfo();
console.log('user ', user)
if(user.name && user.name !== null && user.name !== " " && user.name !== "")
setUserName(user.name)
if(user.profileImage && user.profileImage !== null && user.profileImage !== " " && user.profileImage !== "")
setProfileImage(user.profileImage)
}
await fetchAllTweets();
//eslint-disable-next-line react-hooks/exhaustive-deps
} catch (error) {
console.error(error);
}
};
init();
}, []);
const logout = async () => {
if (!web3auth) {
console.log("web3auth not initialized yet");
return;
}
await web3auth.logout();
setProvider(null);
};
const login = async () => {
if (!web3auth) {
console.log("web3auth not initialized yet");
return;
}
const web3authProvider = await web3auth.connectTo(
WALLET_ADAPTERS.OPENLOGIN,
{
loginProvider: "jwt",
extraLoginOptions: {
domain: APP_CONSTANTS.AUTH0_DOMAIN, // Please append "https://" before your domain
verifierIdField: "sub",
},
}
);
setProvider(web3authProvider);
if(web3authProvider){
let user = await web3auth.getUserInfo();
if(user.name && user.name !== null && user.name !== " " && user.name !== "")
setUserName(user.name)
if(user.profileImage && user.profileImage !== null && user.profileImage !== " " && user.profileImage !== "")
setProfileImage(user.profileImage)
}
};
/*
const getAccounts = async () => {
if (!provider) {
console.log("provider not initialized yet");
return;
}
const rpc = new RPC(provider);
const userAccount = await rpc.getAccounts();
return userAccount;
};
*/
const refresh = (e: any) => {
e.preventDefault();
fetchAllTweets();
};
const fetchAllTweets = async () => {
console.log("fetchalltweetsrunning");
if (!provider) {
console.log("provider not initialized yet");
return;
}
const rpc = new RPC(provider);
try {
let fetchedTweets = await rpc.getAllTweets();
let tweets = [...fetchedTweets];
setTweets(tweets.reverse());
} catch (error) {
console.log("error in fetching tweets", error);
}
};
const upVote = async (tweetIndex: any) => {
if (!provider) {
console.log("provider not initialized yet");
return;
}
try {
const rpc = new RPC(provider);
await rpc.sendUpVoteTransaction(tweetIndex);
fetchAllTweets();
} catch (error) {
console.log("failed to execute upvote transaction", error);
}
};
const addNewTweet = (e: any) => {
e.preventDefault();
if (!provider) {
console.log("provider not initialized yet");
return;
}
try {
const rpc = new RPC(provider);
toast.success("Tweet added successfully", {
position: toast.POSITION.TOP_CENTER,
});
rpc.sendWriteTweetTransaction(newTweetName, newTweetDescription);
setTimeout(function () {
fetchAllTweets();
}, refreshTime);
fetchAllTweets();
} catch (error) {
toast.error("Something went wrong", {
position: toast.POSITION.TOP_LEFT,
});
console.log("failed to execute new tweet transaction", error);
}
};
const addComment = async (event: any, tweetIndex: any) => {
event.preventDefault();
if (!provider) {
console.log("provider not initialized yet");
return;
}
try {
const rpc = new RPC(provider);
toast.success("Comment added successfully - refresh after 30 sec", {
position: toast.POSITION.TOP_CENTER,
});
await rpc.sendAddCommentTransaction(tweetIndex, comment);
fetchAllTweets();
} catch (error) {
toast.error("Something went wrong", {
position: toast.POSITION.TOP_LEFT,
});
console.log("failed to execute add comment transaction", error);
}
};
// Event handlers
const handleCommentChange = async (event: any) => {
setComment(event.target.value);
};
const handleNewTweetNameChange = async (event: any) => {
setNewTweetName(event.target.value);
};
const handleNewTweetDescriptionChange = async (event: any) => {
setNewTweetDescription(event.target.value);
};
const loggedInView = (
<>
<button className="button" onClick={logout}>
Logout
</button>
<div>
<h1>New Tweet</h1>
<Card>
<Card.Body>
<Card.Title>What are you thinking? Tweet it out!</Card.Title>
<Card.Text></Card.Text>
<Form.Control
as="input"
onChange={handleNewTweetNameChange}
placeholder="Tweet Name"
/>
<br></br>
<br></br>
<Form.Control
as="textarea"
onChange={handleNewTweetDescriptionChange}
placeholder="Description"
/>
<br></br>
<FaRetweet onClick={addNewTweet} />
</Card.Body>
</Card>
</div>
<div>
<h1>
All Tweets <FaRecycle onClick={fetchAllTweets} />
</h1>
{(tweets || []).map((tweet: any, i) => (
<div key={i}>
<div>
<Card>
<Card.Body>
<Card.Title>
<FaThumbsUp onClick={(event) => upVote(i)} /> {tweet.name}
</Card.Title>
<p>Total Upvotes: {tweet.upvotes}</p>
<p>Tweeted by: {tweet.fromAddress}</p>
<Card.Text>{tweet.description}</Card.Text>
<div>
<h3>All Comments</h3>
{tweet.comments.map((comment: any, j: any) => (
<div key={j}>
Comment {j + 1}: {comment}
</div>
))}
<h3>New Comment</h3>
<span>
<Form.Control
as="input"
onChange={handleCommentChange}
placeholder="Your comment..."
/>
</span>
<span>
<FaComment onClick={(event) => addComment(event, i)} />
</span>
</div>
</Card.Body>
<a
href={
APP_CONSTANTS.OPENSEA_ASSETS_URL +
"/" +
APP_CONSTANTS.CONTRACT_ADDRESS +
"/" +
i
}
rel="opener"
>
Buy Now
</a>
</Card>
</div>
</div>
))}
</div>
<div></div>
<div id="console" style={{ whiteSpace: "pre-line" }}>
<p style={{ whiteSpace: "pre-line" }}></p>
</div>
</>
);
const unloggedInView = (
<>
<div className="login-account">
<button className="twitter-bg btn" onClick={login}>
<img src="images/twitter-white.png" alt=""></img>
Login to your Twitter account
</button>
</div>
</>
);
return (
<div className="grid">
{provider ? (
<Twitter
logoutButton={logout}
handleNewTweetDescriptionChange={handleNewTweetDescriptionChange}
handleNewTweetNameChange={handleNewTweetNameChange}
addNewTweet={addNewTweet}
fetchAllTweets={fetchAllTweets}
tweets={tweets}
upVote={upVote}
handleCommentChange={handleCommentChange}
addComment={addComment}
refresh={refresh}
username={userName}
profileimage={profileImage}
/>
) : (
unloggedInView
)}{" "}
<ToastContainer />
</div>
// <div className="grid">{provider
// ? loggedInView
// : unloggedInView}</div>
// {/* <div className="grid">{loggedInView}</div> */}
);
}
export default App;
enter image description here
this is a screenshot of my code terminal
You are actually not using torusPlugin (line 38 screenshot) anywhere. Inside your useEffect you created a new const torusPlugin and then you are calling that const instead of the [torusPlugin, ...] state you declared on line 38 of the screenshot. Try to differentiate your variables / constants names otherwise would be difficult for you to identify mistakes.
I am working on yup validation. Whenever it comes to FileList validation, if I left the input blank, I got the following error:
enter image description here
Here is my code:
import React, { useEffect, useMemo, useState } from 'react';
import { useLocation } from 'react-router';
import { useDispatch, useSelector } from '#app/hooks';
import { Button, Dimmer, Dropdown, DropdownItemProps, DropdownProps, Form, Header, Loader, Modal } from 'semantic-ui-react';
import { NewBook, TestBook, UpdateParam } from '#app/reducers/master-data/book/book.model';
import * as yup from "yup";
import { useForm } from 'react-hook-form';
import { yupResolver } from '#hookform/resolvers/yup';
import { useHistory } from 'react-router-dom';
import { _getAllGenres } from '#app/reducers/master-data/genre/genre.slice';
import { _getAllPublisher } from '#app/reducers/master-data/publisher/publisher.slice';
import { _getAllAuthors } from '#app/reducers/master-data/author/author.slice';
import { _getAllDepartment } from '#app/reducers/master-data/department/department.slice';
import { _updateBook, _getAllBooks, _getBookDetail, _uploadBookFile } from '#app/reducers/master-data/book/book.slice';
import { Wrapper } from '#app/components/data-table/StyledComponent';
import { IBookParam } from '#app/reducers/master-data/book/book.service';
interface IProps {
}
interface ErrMessage {
type: string,
message: string
}
const schema = yup.object().shape({
title: yup.string().required('Title cannot blank'),
publishYear: yup.number(),
isPublic: yup.boolean(),
language: yup.string(),
authorIDs: yup.array(),
genreIDs: yup.array(),
description: yup.string(),
// departmentIDs: yup.array(),
publisherID: yup.number(),
file: yup
.mixed()
.required("A random message")
.nullable(false)
.test("Empty file", "You need to provide a file", (value: FileList) => {
let x = value.length !== 0
debugger
return value.length !== 0;
})
.test("type", "Only support PDF file", (value: FileList) => {
return value[0].type === "application/pdf"
})
});
const UpdateBookPage: React.FC<IProps> = (props) => {
const dispath = useDispatch()
const history = useHistory();
useEffect(() => {
dispath(_getAllGenres());
dispath(_getAllPublisher());
dispath(_getAllAuthors());
dispath(_getAllDepartment());
// dispath(_getAllBooks());
dispath(_getBookDetail(id));
}, [])
const search = useLocation().search;
const query = new URLSearchParams(search);
const id = query.get('id') || '';
const genres = useSelector(state => state.genre).genres;
const publishers = useSelector(state => state.publisher).publishers;
const authors = useSelector(state => state.author).authors;
const departments = useSelector(state => state.department).departments;
const book = useSelector(state => state.book.selectedBook);
const isLoading = useSelector(state => state.book.isLoading);
const statusCode = useSelector(state => state.book.statusCode);
// console.log(book)
const defaultDepartments = useMemo<number[]>(() => {
let temp: number[] = []
for (let x of book.departments) {
temp.push(x.id)
};
return temp;
}, [book.departments])
const defaultAuthors = useMemo<number[]>(() => {
let temp: number[] = []
for (let x of book.authors) {
temp.push(Number(x.id))
};
return temp;
}, [book.authors])
const defaultGenres = useMemo<number[]>(() => {
let temp: number[] = []
for (let x of book.genres) {
temp.push(Number(x.id))
};
return temp;
}, [book.genres])
const departmentOptions = useMemo<DropdownItemProps[]>(() => {
let temp: DropdownItemProps[] = []
for (let x of departments) {
temp.push({
key: x.id,
text: x.name,
value: x.id
})
};
return temp;
}, [departments])
const genreOptions = useMemo<DropdownItemProps[]>(() => {
let temp: DropdownItemProps[] = []
for (let x of genres) {
temp.push({
key: x.id,
text: x.name,
value: x.id
})
};
return temp;
}, [genres])
const authorOptions = useMemo<DropdownItemProps[]>(() => {
let temp: DropdownItemProps[] = []
for (let x of authors) {
temp.push({
key: x.id,
text: x.fullName,
value: x.id
})
};
return temp;
}, [authors])
const [openForm, setOpenForm] = useState<boolean>(false)
const [authorSelected, setAuthorSelected] = useState<Number[]>([...defaultAuthors]);
const [genreSelected, setGenreSelected] = useState<Number[]>([...defaultGenres]);
const [departmentSelected, setDepartmentSelected] = useState<Number[]>([...defaultDepartments]);
const [selectedFile, setSelectedFile] = useState<File | null>(null);
const [fileErrorText, setFileErrorText] = useState<string>('');
// const [selectedFile, setSelectedFile] = useState<File|null>(null);
const [isOpen, setIsOpen] = useState<boolean>(false);
const [alertText, setAlertText] = useState<string>('');
const [isFailed, setIsFailed] = useState<boolean>(false);
const [errMessage, setErrMessage] = useState<ErrMessage>({
type: '',
message: ''
})
const { register, handleSubmit, formState: { errors }, setValue, trigger } = useForm<TestBook>({
resolver: yupResolver(schema),
// defaultValues: defaultBook
});
useEffect(() => {
if (book) {
setInitValue()
}
}, [book])
const setInitValue = () => {
setValue('title', book.title)
setValue('publishYear', book.publishYear)
setValue('authorIDs', [...defaultAuthors])
setValue('language', 'vi')
setValue('departmentIDs', [...defaultDepartments])
setValue('description', book.description)
setValue('genreIDs', [...defaultGenres])
setValue('isPublic', book.isPublic)
setValue('publisherID', Number(book.publisher.id))
}
// console.log(defaultAuthors, defaultDepartments, defaultGenres)
const handleSubmitBtn = async (data: NewBook) => {
debugger
console.log(data);
const valid = validateData();
debugger
if (valid) {
data.authorIDs = authorSelected.concat(defaultAuthors);
data.genreIDs = genreSelected.concat(defaultGenres)
data.departmentIDs = departmentSelected.concat(defaultDepartments)
const updateParam: UpdateParam = {
id: id,
newBook: data
}
console.log(data);
console.log(selectedFile);
try {
debugger
await dispath(_updateBook(updateParam)).then(() => {
if (statusCode == 200) {
if (selectedFile != null) {
let formData = new FormData();
formData.append("FILE", selectedFile);
formData.append("NAME", selectedFile.name);
const param: IBookParam = {
id: localStorage.getItem("BOOKID") || '',
file: formData
}
console.log(param.file);
console.log(param.id);
dispath(_uploadBookFile(param)).then(() => {
if (statusCode == 200) {
setIsOpen(true);
console.log(isOpen);
setAlertText("Update successfully")
} else {
setIsOpen(true)
setAlertText("An error has occured. Please try again later");
setIsFailed(true);
}
})
} else {
return;
}
}
console.log(data);
})
}
catch {
setIsOpen(true)
setAlertText("An error has occured. Please try again later");
setIsFailed(true);
}
}
}
const validateData = (): boolean => {
let x = authorSelected.concat(defaultAuthors)
let y = genreSelected.concat(defaultGenres)
let z = departmentSelected.concat(defaultDepartments)
debugger
if (authorSelected.concat(defaultAuthors).includes(0)) {
setErrMessage({
type: "AUTHOR",
message: "At least one author must be selected"
});
return false;
} else if (genreSelected.concat(defaultGenres).includes(0)) {
setErrMessage({
type: "GENRE",
message: "At least one genre must be selected",
});
return false;
} else if (departmentSelected.concat(defaultDepartments).includes(0)) {
setErrMessage({
type: "DEPARTMENT",
message: "At least one department must be selected",
});
return false;
}
return true;
}
const handleAddItem = (data: DropdownProps, type: string) => {
let val = JSON.stringify(data.value)
let numArr: Number[] = []
val = val.substring(1, val.length - 1)
let valArr = val.split(',');
// console.log(valArr);
for (let x of valArr) {
numArr.push(Number(x))
// console.log(numArr)
}
console.log(numArr)
// const y: Number[] = numArr
switch (type) {
case "AUTHOR":
setValue("authorIDs", numArr)
setAuthorSelected(numArr)
break;
case "GENRE":
setValue("genreIDs", numArr)
setGenreSelected(numArr);
break;
case "DEPARTMENT":
// if(numArr.length > 5){
// setErrMessage({
// type: "Department",
// message: "You can only select maximum of 5 departments"
// })
// break;
// }
setValue("departmentIDs", numArr)
setDepartmentSelected(numArr);
break;
}
}
const handleSelectFile = (event: any) => {
console.log(event.target.files[0]);
setSelectedFile(event.target.files[0]);
}
const handleCancelAction = () => {
history.push('/master-data/manage-book')
}
useEffect(() => {
console.log(authorSelected)
console.log(genreSelected)
console.log(departmentSelected)
}, [authorSelected, genreSelected, departmentSelected])
return (
<div className="form-create-book">
<Header>Update book</Header>
{
isLoading && (
<Wrapper style={{ padding: '40px 0' }}>
<Dimmer inverted active={true}>
<Loader>Loading</Loader>
</Dimmer>
</Wrapper>)
}
{
!isLoading && (
<div>
<Modal
size={"tiny"}
open={isOpen}
>
<Modal.Content>
<h2 style={{textAlign: 'center'}}>{alertText}</h2>
</Modal.Content>
<Modal.Actions>
{!isFailed &&
<Button negative onClick={() => setIsOpen(false)}>
Close
</Button>
}
<Button positive onClick={() => history.push("/librarian/master-data/manage-book")}>
Ok
</Button>
</Modal.Actions>
</Modal>
<Form className="create-book-form" onSubmit={handleSubmit(handleSubmitBtn)}>
<Form.Field>
<label className='dot-required'>Title</label>
<input {...register('title')} className="text-field" />
<p>{errors.title?.message}</p>
</Form.Field>
<Form.Field>
<label>Description</label>
<textarea {...register('description')} className="textarea-field" />
<p>{errors.description?.message}</p>
</Form.Field>
<Form.Field>
<label className='dot-required'>Publish Year</label>
<input className="text-field" {...register('publishYear')} />
<p>{errors.publishYear?.message}</p>
</Form.Field>
<Form.Field>
<label className='dot-required'>PDF File</label>
<input {...register('file')} className="text-field" accept="application/pdf" type="file" name="file" onChange={handleSelectFile} />
<p>{errors.file?.message}</p>
</Form.Field>
<Form.Field>
<label className='dot-required'>Access Permission</label>
<select defaultValue={book.isPublic ? 1 : 0} className="text-field" {...register('isPublic')}>
<option value={1}>Public</option>
<option value={0}>Restricted</option>
</select>
<p>{errors.isPublic?.message}</p>
</Form.Field>
<Form.Field>
<label className='dot-required'>Publisher</label>
<select className="text-field" {...register('publisherID')} >
{
publishers.map((e) => {
if (e.id === book.publisher.id)
return (<option selected value={e.id}>{e.name}</option>)
else
return (<option value={e.id}>{e.name}</option>)
}
)
}
</select>
<p>{errors.publisherID?.message}</p>
</Form.Field>
<Form.Field>
<label className='dot-required'>Authors</label>
<Dropdown className="text-field" onChange={(e, data) => handleAddItem(data, "AUTHOR")} placeholder='Authors' fluid multiple selection options={authorOptions} defaultValue={defaultAuthors} />
<p>{errMessage.type == "AUTHOR" ? errMessage.message : ''}</p>
</Form.Field>
<Form.Field>
<label className='dot-required'>Genre</label>
<Dropdown className="text-field" onChange={(e, data) => handleAddItem(data, "GENRE")} placeholder='Genres' fluid multiple selection options={genreOptions} defaultValue={defaultGenres} />
<p>{errMessage.type == "GENRE" ? errMessage.message : ''}</p>
</Form.Field>
<Form.Field>
<label className='dot-required'>Department</label>
<Dropdown className="text-field" onChange={(e, data) => handleAddItem(data, "DEPARTMENT")} placeholder='Genres' fluid multiple selection options={departmentOptions} defaultValue={defaultDepartments} />
<p>{errMessage.type == "DEPARTMENT" ? errMessage.message : ''}</p>
</Form.Field>
<Button
content="Submit"
// onClick={handleSubmit(handleSubmitBtn)}
className="ui inverted green button"
/>
<Button
color="black"
content="Cancel"
onClick={() => handleCancelAction()}
className="negative ui button"
/>
</Form>
</div>
)
}
</div>
);
};
export default UpdateBookPage;
When I check the source tab, I find out that the problem comes from here:
But I don't know how to solve it.
replace
.required("A random message")
.nullable(false)
to
.test("fileLength", "A random message", (value) => {
return !!value.length
})
So I'm trying to generate alerts for users that attempt to access weather data for invalid cities via the OpenWeatherMaps API.
I'm mostly there. However, when I test this out, two things happen:
Browser generates the proper alert.
However, once you click on the confirmation button for the alert...
"Unhandled Rejection (TypeError): Cannot destructure property 'data' of '(intermediate value)' as it is undefined."
Here is the code that I'm currently using:
const fetchWeather = async (query) => {
const { data } = await axios.get(
URL,
{
params: {
q: query,
units: "metric",
APPID: API_KEY,
},
}).catch (function (error) {
alert(error.response.data.message)
})
};
Full code:
Search.jsx component:
import React, { useState } from "react";
import fetchWeather from "../api/fetchWeather";
import { makeStyles } from "#material-ui/core/styles";
import TextField from "#material-ui/core/TextField";
import InputAdornment from '#material-ui/core/InputAdornment';
import SearchIcon from '#material-ui/icons/Search';
const Search = () => {
let [displayResults, setDisplayResults] = useState(false);
let [query, setQuery] = useState("");
let [feelsLike, setFeelsLike] = useState(0);
let [mainTemp, setMainTemp] = useState(0);
let [description, setDescription] = useState("");
let [main, setMain] = useState("");
let [iconID, setIconID] = useState("");
let [windSpeed, setWindSpeed] = useState("");
let [windGust, setWindGust] = useState("");
let [windDirection, setWindDirection] = useState("");
let [name, setName] = useState("");
let [country, setCountry] = useState("");
const useStyles = makeStyles((theme) => ({
button: {
backgroundColor: "#FDB124",
color: "black",
fontFamily: "Mortal Kombat",
"&:hover": {
background: "#B57602",
},
},
root: {
"& > *": {
display: 'flex',
margin: theme.spacing(1),
// width: "25ch",
},
input: {
color: "white",
},
primary: {
backgroundColor: "#FDB124",
},
"& label.Mui-focused": {
color: "#FDB124",
},
"& label": {
color: "#FDB124",
fontFamily: "Mortal Kombat",
},
"& input": {
color: "#FDB124",
fontFamily: "Mortal Kombat",
},
"& .MuiInput-underline:after": {
borderBottomColor: "#FDB124",
},
"& .MuiOutlinedInput-root": {
"& fieldset": {
borderColor: "#FDB124",
},
"&:hover fieldset": {
borderColor: "#FDB124",
},
"&.Mui-focused fieldset": {
borderColor: "#FDB124",
},
},
},
}));
const weatherSearch = async (e) => {
if (e.key === "Enter") {
const data = await fetchWeather(query);
setDisplayResults(true);
setFeelsLike(data.main.feels_like);
setMainTemp(data.main.temp);
setDescription(data.weather[0].description);
setMain(data.weather[0].main);
setIconID(data.weather[0].icon);
setWindSpeed(data.wind.speed);
setWindGust(data.wind.gust);
setWindDirection(data.wind.deg);
setName(data.name);
setCountry(data.sys.country);
setQuery("");
}
};
const classes = useStyles();
return (
<div>
<h1 className="cityChoose">CHOOSE YOUR CITY:</h1>
<TextField
id="outlined-basic"
label="Enter City"
variant="outlined"
color="secondary"
size="small"
spellCheck="false"
className={classes.root}
value={query}
onChange={(e) => setQuery(e.target.value)}
onKeyPress={weatherSearch}
InputProps={{
startAdornment: (
<InputAdornment position="start" style={{color: "#FDB124"}}>
<SearchIcon />
</InputAdornment>
),
}}
/>
{displayResults ? null : <h4>Example: Chicago, IL, US</h4>}
{displayResults ? (
<>
<h1>The current weather in {name}, {country} is:</h1>
<span>
<div>
{description}
<br />
<img
src={"http://openweathermap.org/img/wn/" + iconID + "#2x.png"}
/>
</div>
<h2>Temperature:</h2>
<br />
<div>
{(mainTemp * 1.8 + 32).toFixed(1)} °F / {mainTemp.toFixed(1)}{" "}
°C
</div>
<br />
<br />
<h2>Winds:</h2>
<div>Wind Direction: {windDirection}</div>
<div>Wind Speed: {windSpeed} MPH</div>
<div>Wind Gusts: {windGust} MPH</div>
</span>
</>
) : null}
</div>
);
};
export default Search;
fetchWeather.jsx:
import React from "react";
import axios from "axios";
const URL = "https://api.openweathermap.org/data/2.5/weather";
const API_KEY = "*key is here*";
const fetchWeather = async (query) => {
const { data } = await axios.get(
URL,
{
params: {
q: query,
units: "metric",
APPID: API_KEY,
},
}).catch (function (error) {
if (error.response) {
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
console.log(error.request);
} else {
console.log("Error: ", error.message);
}
});
console.log(data);
return data;
};
export default fetchWeather;
Ok, so the problem you're having has to do with the fact that axios throws an error and does not return an object with key data back to const { data } = await axios.get(. Fixing this is quite straightforward.
The reason it cannot destructure data from your bad axios call is because you're not accommodating it inside the catch block
.catch (function (error) {
alert(error.response.data.message)
})
Your catch block should instead look like this:
.catch (error => {
return {data: error.response.data ? error.response.data : 'No data'}
}
)
So the final (and working) version of your fetchWeather function is...
const fetchWeather = async (query) => {
const { data } = await axios.get(
'https://httpstat.us/400',
{
params: {
q: query,
units: "metric",
APPID: 'XXXXXXXX',
},
})
.catch (error => {
return {data: error.response.data ? error.response.data : 'No data'}
}
)
console.log(data)
};
You can try it with these two test URLs:
https://httpstat.us/200 returns 200 OK
https://httpstat.us/400 returns 400 Bad Request
The latter will trigger the catch.
Please keep in mind that my code, as written, will throw an error if you're calling a domain that does not resolve to an ip (e.g. http://hskjfhshgsg.com/api/sss/sss or something like that.)
Try to check for the error like this:
if (error.response) {
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
console.log(error.request);
} else {
console.log("Error", error.message);
}
Working sample: https://codesandbox.io/s/openweathermap-test-forked-35781?file=/src/index.js:434-749
I'm using hooks and Context when after login my URL refreshing sometimes and get this Error Maximum update depth exceeded and my page not loading when refresh page everything is Ok!
this code my Login Page :
function LoginView(props) {
const classes = useStyles()
const [Username, setUsername] = useState('');
const [Password, setPassword] = useState('');
const { getUserLogin, isLogin } = useContext(UserContext)
const handelSubmit = (e) => {
console.log(Username, Password)
if (Username.length < 1) {
alert("لطفا نام کاربری را وارد نمایید")
if (Password.length < 1) {
alert("لطفا رمز عبور را واردنمایید")
}
}
let uuid = uuidv1()
console.log(uuid)
localStorage.setItem('myUUID', uuid)
let xml = 'exampel xlm (srver is SOAP)';
console.log(xml)
getUserLogin(xml)
}
useEffect(() => {
if (isLogin) {
props.history.push("/MainPage")
}
})
return (
<div style={{ direction: 'rtl', }}>
<MyLogo />
<div className={classes.root} >
<div className='textfiled'>
<TextField
className={classes.txt}
name='username'
inputProps={{ style: { textAlign: 'center' } }}
onChange={(e) => setUsername(e.target.value)}
placeholder='نام کاربری' ></TextField>
</div>
<div >
<TextField
className={classes.txt}
inputProps={{ style: { textAlign: 'center' } }}
name='password'
type='password'
onChange={(e) => setPassword(e.target.value)}
placeholder='رمز عبور' ></TextField>
</div>
<div>
<Button color={'inherit'} className={classes.btn} onClick={() => handelSubmit()} > ورود</Button>
</div>
</div>
</div>
)
}
export default withRouter(LoginView);
after submitting my cod get some error in console google I read this post
Maximum update depth exceeded
and change my onclick function but steel error Maximum update depth exceeded
and this is my Context :
export const UserContext = createContext()
export const UserContextDispacher = createContext();
const UserProvider = (props) => {
const [user, setUser] = useState({ username: '', password: '', })
const [isLogin, setisLogin] = useState(false)
const getUserLogin = (value) => {
axios.post('https://exampel.com/myexampel.asmx', value, { headers: { 'Content-Type': 'text/xml;charset=UTF-8' } }).then(function (response) {
// console.log(response)
var options = {
attributeNamePrefix: "#_",
attrNodeName: "attr", //default is 'false'
textNodeName: "#text",
ignoreAttributes: true,
ignoreNameSpace: false,
allowBooleanAttributes: false,
parseNodeValue: true,
parseAttributeValue: false,
trimValues: true,
cdataTagName: "__cdata", //default is 'false'
cdataPositionChar: "\\c",
localeRange: "", //To support non english character in tag/attribute values.
parseTrueNumberOnly: false,
attrValueProcessor: a => he.decode(a, { isAttributeValue: true }),//default is a=>a
tagValueProcessor: a => he.decode(a) //default is a=>a
};
// Intermediate obj
var tObj = parser.getTraversalObj(response.data, options);
var jsonObj = parser.convertToJson(tObj, options);
//set Token
var token = jsonObj["soap:Envelope"]["soap:Body"].AuthenticateUserResponse.Token
var authResult = jsonObj["soap:Envelope"]["soap:Body"].AuthenticateUserResponse.AuthenticateUserResult
if (authResult != false) {
localStorage.setItem('mytoken', token)
localStorage.setItem('myisLogin', authResult)
setisLogin(true)
} else {
localStorage.setItem('myisLogin', authResult)
setisLogin(false)
}
return authResult
}).catch(function (error) {
// console.log("erorr in send to login : " + error)
})
}
return (
<UserContext.Provider value={{ user, getUserLogin, isLogin }}>
<UserContextDispacher.Provider>
{props.children}
</UserContextDispacher.Provider>
</UserContext.Provider>
)
}
export default withRouter(UserProvider);
how to fix it this error?
thank for helping me
UPDATE
if (authResult != false) {
localStorage.setItem('mytoken', token)
localStorage.setItem('myisLogin', authResult)
setisLogin(true)
props.history.push("/MainPage");
}
and delete useEffect from loginview.js
useEffect runs every time a change occurs so useEffect is getting triggered infinitely many times so the error.
Solution : Use isLogin as dependency for useEffect.
useEffect(() => {
if (isLogin) {
props.history.push("/MainPage")
}
},[isLogin])