I've written these actions and the saga to listen for them.
export async function addToWishlistApi(id: number) {
console.log("addToWishlistApi HELLO CAN ANYBODY HEAR ME");
const res = await axios.get(WishlistUrls.add(id));
console.log(res);
}
export function* addToWishlistSaga({ id }: { id: number }): Saga<void> {
console.log("addToWishlistSaga HELLO CAN ANYBODY HEAR ME");
try {
const res = yield call(addToWishlistApi, id);
console.log(res);
const wishlist = yield call(getCurrentWishlist);
console.log("WISHLIST", wishlist);
if (wishlist.contains(id))
yield put({ type: DealActionTypes.wishlistSuccess });
} catch (error) {
console.log("ERROR", error);
}
}
export async function getCurrentWishlist(): Promise<number[]> {
const res = await axios.get(WishlistUrls.getWishlist);
console.log(res.data.includes("WISHLIST-2.HTML"));
const $ = cheerio.load(res.data);
const tags = $(".button.yith-wcqv-button");
const idStrings: string[] = [];
tags.each((i, tag) => {
idStrings.push(tag.attribs["data-product_id"]);
});
const wishlist = idStrings.map(n => Number(n));
return wishlist;
}
export default function* wishlistSaga(): Saga<void> {
yield all([
yield takeEvery(DealActionTypes.addToWishlistStart, addToWishlistSaga),
yield takeEvery(
DealActionTypes.removeFromWishlistStart,
removeFromWishlistSaga
)
]);
}
I'm trying to test with recordSaga
import { runSaga } from "redux-saga";
export default async function recordSaga(saga, initialAction) {
const dispatched = [];
await runSaga(
{ dispatch: action => dispatched.push(action) },
saga,
initialAction
).done;
return dispatched;
}
And here are my tests:
describe("addToWishlistSaga", () => {
const startAction: Type.AddToWishlistStartAction = {
type: Types.addToWishlistStart,
id: deal.id
};
const successAction: Type.WishlistSuccessAction = {
type: Types.wishlistSuccess
};
const failureAction: Type.AddToWishlistFailureAction = {
type: Types.addToWishlistFailure,
id: deal.id
};
fit("dispatches a success action on success", async () => {
const dispatched = await recordSaga(wishlistSaga, startAction);
expect(dispatched).toContainEqual(successAction);
});
xit("dispatches a failure action on failure", async () => {
mock.onGet(WishlistUrls.add(deal.id)).networkErrorOnce();
const dispatched = await recordSaga(wishlistSaga, startAction);
expect(dispatched).toContainEqual(failureAction);
});
});
});
The saga setup and test setup are identical to what I've used successfully in other projects, but for some reason addToWishlistSaga is never being run. None of the desperate log statements are being printed, and dispatched comes back empty.
What am I doing wrong here? My head is about to explode.
Related
i tried to add the display_1 and diplay_2 in my mutation variables and tried to console.log it but the output is (undefined, false, undefined) for the console.log(data,loading,error)
const CREATE_T09_SCREENSHOT = gql`
mutation
createT09ScreenShot(
$screenshot_window_1: String!,
$screenshot_window_2: String!,
) {
createT09ScreenShot(
screenshot_window_1: $screenshot_window_1,
screenshot_window_2: $screenshot_window_2,
) {
screenshot_window_1
screenshot_window_2
}
}
`;
const SaveLogsButton = () => {
const [createT09ScreenShot, { loading, error, data }] = useMutation(CREATE_T09_SCREENSHOT);
const handleClick = async () => {
const screenshotData = await saveImage();
if (screenshotData){
const { display_1, display_2 } = screenshotData;
createT09ScreenShot({
variables: {
screenshot_window_1: display_1,
screenshot_window_2: display_2,
},
});
}
console.log(data)
console.log(loading)
console.log(error)
};
i also tried to do this but it give me an error
const handleClick = async () => {
await saveImageFunction();
const { display_1, display_2 } = saveImage;
createT09ScreenShot({
variables: {
and here is the error
Unhandled Promise Rejection: TypeError: Right side of assignment cannot be destructured
I think you have some error inside handleclick function of saveImage destructurable object.
You need to replace your handleClick function code with this code:
const handleClick = async () => {
const screenshotData = await saveImageFunction();
const { display_1, display_2 } = screenshotData;
createT09ScreenShot({
variables: {
screenshot_window_1: display_1,
screenshot_window_2: display_2,
},
});
};
I'm trying to implement redux saga in my old project and i get strange error.
I'm getting back the userData with all user details but my middleware logger tells me that sign_in_failed fires instead of sign_in_success with this error:
Cannot read property of undefined data() Firebase.
So i tried to do optional chaining and i also tried the old way of deep property check (with &&) but this didnt help. Also, i cant anymore perform a stripe payments due to this error because stripe cant see the user.
UserSaga.jsx
import { takeLatest, all, call, put } from 'redux-saga/effects'
import { USER_ACTIONS_TYPES } from '../../actions/user/userActionsTypes'
import {
signInSuccess,
signInFailed,
signUpSuccess,
signUpFailed,
signOutSuccess,
signOutFailed
} from '../../actions/user/userActionCreator'
import {
getCurrentUser,
createUserDocumentFromAuth,
createAuthUserWithEmailAndPassword,
signInWithGooglePopup,
signInAuthUserWithEmailAndPassword,
signOutAuthUser
} from '../../../database/firebase.config'
export function* getUserSnapshot(userAuth, additionalInformation) {
try {
const userSnapshot = yield call(
createUserDocumentFromAuth,
userAuth,
additionalInformation
);
//yield put(signInSuccess({ id: userSnapshot?.id, ...userSnapshot.data()}));
// console.log('userSnapshot2>>>>>>>>>', ...userSnapshot.data())
const id = userSnapshot?.id;
const userData = userSnapshot.data()
const {createdAt, email, password}= userData
yield put(signInSuccess({ id, createdAt, email, password }));
console.log('userSnapshot2>>>>>>>>>', userSnapshot)
} catch (error) {
yield put(signInFailed(error.message))
}
}
export function* signInWithGoogle() {
try {
const { user } = yield call(signInWithGooglePopup)
yield call(getUserSnapshot, user)
} catch (error) {
yield put(signInFailed(error))
}
}
export function* signInWIthEmail({ payload: { email, password } }) {
try {
const { user } = yield call(signInAuthUserWithEmailAndPassword, email, password)
yield call(getUserSnapshot, user)
} catch (error) {
yield put(signInFailed(error))
}
}
export function* isUserAuth() {
try {
const userAuth = yield call(getCurrentUser)
if (!userAuth) return;
yield call(getUserSnapshot, userAuth)
} catch (error) {
yield put(signInFailed(error))
}
}
export function* signUpWIthEmail({ payload: { email, password, displayName } }) {
try {
const { user } = yield call(createAuthUserWithEmailAndPassword, email, password)
yield put(signUpSuccess(user, { displayName }))
} catch (error) {
yield put(signUpFailed(error))
}
}
export function* signOut() {
try {
yield call(signOutAuthUser)
yield put(signOutSuccess())
} catch (error) {
yield put(signOutFailed(error))
}
}
export function* signInAfterSignUp({ payload: { user, additionalDetails } }) {
yield call(getUserSnapshot, user, additionalDetails)
}
export function* onGoogleSignInStart() {
yield takeLatest(USER_ACTIONS_TYPES.GOOGLE_SIGN_IN_START, signInWithGoogle)
}
export function* onCheckUserSession() {
yield takeLatest(USER_ACTIONS_TYPES.CHECK_USER_SESSION, isUserAuth)
}
export function* onEmailSignInStart() {
yield takeLatest(USER_ACTIONS_TYPES.EMAIL_SIGN_IN_START, signInWIthEmail)
}
export function* onSignUpStart() {
yield takeLatest(USER_ACTIONS_TYPES.SIGN_UP_START, signUpWIthEmail)
}
export function* onSignUpSuccess() {
yield takeLatest(USER_ACTIONS_TYPES.SIGN_IN_SUCCESS, signInAfterSignUp)
}
export function* onSignOutStart() {
yield takeLatest(USER_ACTIONS_TYPES.SIGN_OUT_START, signOut)
}
export function* userSagas() {
yield all([
call(onCheckUserSession),
call(onGoogleSignInStart),
call(onEmailSignInStart),
call(onSignUpStart),
call(onSignUpSuccess),
call(onSignOutStart),
call(onSignUpSuccess)
])
}
firebase.config.js
// Initialize Firebase and Oauth
initializeApp(firebaseConfig);
const googleProvider = new GoogleAuthProvider();
googleProvider.setCustomParameters({
prompt: "select_account"
})
//Initialize GAuth with popup signin method
export const auth = getAuth()
export const signInWithGooglePopup = () => signInWithPopup(auth, googleProvider)
// export const signInWithGoogleRedirect = () => signInWithRedirect(auth, googleProvider)
// Initialize Firestore
export const db = getFirestore()
// get the conllection created with all docs
export const getCollectionWithDocuments = async() => {
const collectionRef = collection(db, 'categories')
const q = query(collectionRef)
const querySnapShot = await getDocs(q)
return querySnapShot.docs.map(docSnapshot => docSnapshot.data())
}
//Create a user document
export const createUserDocumentFromAuth = async(userAuth, additionalInformation = {}) => {
if (!userAuth) return;
const userDocRef = doc(db, 'users', userAuth.uid)
// console.log('userRef>>', userDocRef)
const userSnapshot = await getDoc(userDocRef)
// console.log('just snapshot>>>', snapShot)
// console.log('if shot exist>>', snapShot.exists())
if (!userSnapshot.exists()) {
const { displayName, email } = userAuth
const createdAt = new Date();
try {
await setDoc(userDocRef, {
displayName,
email,
createdAt,
...additionalInformation
})
} catch (error) {
console.log("error creating user", error.message)
}
}
return userSnapshot;
}
export const createAuthUserWithEmailAndPassword = async(email, password) => {
if (!email || !password) return;
return await createUserWithEmailAndPassword(auth, email, password)
}
export const signInAuthUserWithEmailAndPassword = async(email, password) => {
if (!email || !password) return;
return await signInWithEmailAndPassword(auth, email, password)
}
export const signOutAuthUser = async() => await signOut(auth)
export const onAuthObserver = (callback) => onAuthStateChanged(auth, callback)
//Create a collection of document in firestore (call it ones inside useeffect to avoid mutations)
export const createCollectionWithDocuments = async(collectionName, objectsToAdd) => {
const collectionRef = collection(db, collectionName)
const batch = writeBatch(db)
objectsToAdd.forEach(object => {
const docRef = doc(collectionRef, object.title.toLowerCase())
batch.set(docRef, object)
})
await batch.commit()
console.log('collection created')
}
export const getCurrentUser = () => {
return new Promise((resolve, reject) => {
const unsubscribe = onAuthStateChanged(
auth,
(userAuth) => {
unsubscribe();
resolve(userAuth);
// console.log(userAuth)
},
reject)
})
}
userReducer.jsx
export const INITIAL_STATE = {
currentUser: null,
isLoading: false,
error: null
}
export const userReducer = (state = INITIAL_STATE, action) => {
const { type, payload } = action;
switch (type) {
case USER_ACTIONS_TYPES.SIGN_IN_SUCCESS:
return {
...state,
currentUser: payload,
error: null
}
case USER_ACTIONS_TYPES.SIGN_OUT_SUCCESS:
return {
...state,
currentUser: null
}
case USER_ACTIONS_TYPES.SIGN_OUT_FAILED:
case USER_ACTIONS_TYPES.SIGN_UP_FAILED:
case USER_ACTIONS_TYPES.SIGN_IN_FAILED:
return {
...state,
error: payload
}
default:
return state
}
}
userActions.js
export const emailSignInStart = (email, password) => createActions(USER_ACTIONS_TYPES.EMAIL_SIGN_IN_START, { email, password })
export const signInSuccess = user => createActions(USER_ACTIONS_TYPES.SIGN_IN_SUCCESS, user)
export const signInFailed = error => createActions(USER_ACTIONS_TYPES.SIGN_IN_FAILED, error)
I am trying to load a website to my localhost but keep running into an error that says Uncaught ReferenceError: keyword is not defined at useFetch (:3000/src/hooks/useFetch.jsx:21:7) at TransactionsCard (:3000/src/components/Transactions.jsx:33:18). The issue hapens in my code where I'm fetching gifs from my API at giphy developer.
Here is the source code:
Transactions.jsx:
import React, { useEffect, useState } from "react";
import { ethers } from "ethers";
import { contractABI, contractAddress } from "../utils/constants";
export const TransactionContext = React.createContext();
const { ethereum } = window;
const createEthereumContract = () => {
const provider = new ethers.providers.Web3Provider(ethereum);
const signer = provider.getSigner();
const transactionsContract = new ethers.Contract(contractAddress, contractABI, signer);
return transactionsContract;
};
export const TransactionsProvider = ({ children }) => {
const [formData, setformData] = useState({ addressTo: "", amount: "", keyword: "", message: "" });
const [currentAccount, setCurrentAccount] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [transactionCount, setTransactionCount] = useState(localStorage.getItem("transactionCount"));
const [transactions, setTransactions] = useState([]);
const handleChange = (e, name) => {
setformData((prevState) => ({ ...prevState, [name]: e.target.value }));
};
const getAllTransactions = async () => {
try {
if (ethereum) {
const transactionsContract = createEthereumContract();
const availableTransactions = await transactionsContract.getAllTransactions();
const structuredTransactions = availableTransactions.map((transaction) => ({
addressTo: transaction.receiver,
addressFrom: transaction.sender,
timestamp: new Date(transaction.timestamp.toNumber() * 1000).toLocaleString(),
message: transaction.message,
keyword: transaction.keyword,
amount: parseInt(transaction.amount._hex) / (10 ** 18)
}));
console.log(structuredTransactions);
setTransactions(structuredTransactions);
} else {
console.log("Ethereum is not present");
}
} catch (error) {
console.log(error);
}
};
const checkIfWalletIsConnect = async () => {
try {
if (!ethereum) return alert("Please install MetaMask.");
const accounts = await ethereum.request({ method: "eth_accounts" });
if (accounts.length) {
setCurrentAccount(accounts[0]);
getAllTransactions();
} else {
console.log("No accounts found");
}
} catch (error) {
console.log(error);
}
};
const checkIfTransactionsExists = async () => {
try {
if (ethereum) {
const transactionsContract = createEthereumContract();
const currentTransactionCount = await transactionsContract.getTransactionCount();
window.localStorage.setItem("transactionCount", currentTransactionCount);
}
} catch (error) {
console.log(error);
throw new Error("No ethereum object");
}
};
const connectWallet = async () => {
try {
if (!ethereum) return alert("Please install MetaMask.");
const accounts = await ethereum.request({ method: "eth_requestAccounts", });
setCurrentAccount(accounts[0]);
window.location.reload();
} catch (error) {
console.log(error);
throw new Error("No ethereum object");
}
};
const sendTransaction = async () => {
try {
if (ethereum) {
const { addressTo, amount, keyword, message } = formData;
const transactionsContract = createEthereumContract();
const parsedAmount = ethers.utils.parseEther(amount);
await ethereum.request({
method: "eth_sendTransaction",
params: [{
from: currentAccount,
to: addressTo,
gas: "0x5208", //21,000 gwei in hexadecimal form
value: parsedAmount._hex,
}],
});
const transactionHash = await transactionsContract.addToBlockchain(addressTo, parsedAmount, message, keyword);
setIsLoading(true);
console.log(`Loading - ${transactionHash.hash}`);
await transactionHash.wait();
console.log(`Success - ${transactionHash.hash}`);
setIsLoading(false);
const transactionsCount = await transactionsContract.getTransactionCount();
setTransactionCount(transactionsCount.toNumber());
window.location.reload();
} else {
console.log("No ethereum object");
}
} catch (error) {
console.log(error);
throw new Error("No ethereum object");
}
};
useEffect(() => {
checkIfWalletIsConnect();
checkIfTransactionsExists();
}, [transactionCount]);
return (
<TransactionContext.Provider
value={{
transactionCount,
connectWallet,
transactions,
currentAccount,
isLoading,
sendTransaction,
handleChange,
formData,
}}
>
{children}
</TransactionContext.Provider>
);
};
useFetch.jsx:
import { useEffect, useState } from 'react';
const API_KEY = import.meta.env.VITE_GIPHY_API;
const useFetch = () => {
const [gifUrl, setGifUrl] = useState("");
const fetchGifs = async () => {
try {
const response = await fetch(`https://api.giphy.com/v1/gifs/search?api_key=${API_KEY}&q=${keyword.split(" ").join("")}&limit=1`)
const { data } = await response.json();
setGifUrl(data[0]?.images?.downsized_medium?.url)
} catch (error) {
setGifUrl('https://metro.co.uk/wp-content/uploads/2015/05/pokemon_crying.gif?quality=90&strip=all&zoom=1&resize=500%2C284')
}
}
useEffect(() => {
if (keyword) fetchGifs();
}, [keyword]);
return gifUrl;
}
export default useFetch;
When I comment out the lines that use 'keyword' it launches with no errors. This is at lines 14, 18, and 58-62 of Transactions.jsx.
Any help would be greatly appreciated, thank you!
The problem here is that you have not define keyword inside your useFetch function.
If you are trying to pass the keyword from the place where you use useFetch then do something like below and use the useFetch like const gifUrl = useFetch(<keyword>)
import { useEffect, useState } from 'react';
const API_KEY = import.meta.env.VITE_GIPHY_API;
const useFetch = (keyword) => {
const [gifUrl, setGifUrl] = useState("");
const fetchGifs = async () => {
try {
const response = await fetch(`https://api.giphy.com/v1/gifs/search?api_key=${API_KEY}&q=${keyword.split(" ").join("")}&limit=1`)
const { data } = await response.json();
setGifUrl(data[0]?.images?.downsized_medium?.url)
} catch (error) {
setGifUrl('https://metro.co.uk/wp-content/uploads/2015/05/pokemon_crying.gif?quality=90&strip=all&zoom=1&resize=500%2C284')
}
}
useEffect(() => {
if (keyword) fetchGifs();
}, [keyword]);
return gifUrl;
}
export default useFetch;
or even try adding default value for key work like below.
const useFetch = (keyword = "some keyword") => {
I have a NotifiCard component and a ReplyComment component
When I run the LookforReply function, the GETONECOMMENT_REQUEST and LOAD_POST_REQUEST dispatches are executed, and the data comes into onecomment.
which is
const {onecomment} = useSelector((state) => state.post);
And I also want to pass the {item:one comment} data in the ReplyComment using navigation.navigate.
However, when we run our code, the data does not come into ReplyComment immediately, so it causing an error.
this is my code
(NotifiCard.js)
const NotifiCard = ({item}) => {
const dispatch = useDispatch();
const navigation = useNavigation();
const {onecomment} = useSelector((state) => state.post);
const LookforReply = useCallback(() => {
dispatch({
type:GETONECOMMENT_REQUEST,
data:item?.CommentId,
}),
dispatch({
type: LOAD_POST_REQUEST,
data:item.PostId,
}),
navigation.navigate('ReplyComment',{itemm:onecomment})
},[]);
return (
<LookContainer onPress={LookforReply}>
<Label>대댓보기</Label>
</LookContainer>
);
};
when dispatch GETONECOMMENT_REQUEST, getonecommentAPI this api run and get data from backend router
(postsaga.js)
function getonecommentAPI(data) {
return axios.get(`/post/${data}/getonecomment`);
}
function* getonecomment(action) {
try {
const result = yield call(getonecommentAPI, action.data);
yield put({
type: GETONECOMMENT_SUCCESS,
data: result.data,
});
} catch (err) {
console.error(err);
yield put({
type: GETONECOMMENT_FAILURE,
error: err.response.data,
});
}
}
which is this backend router
(backend/post.js)
router.get('/:onecommentId/getonecomment', async (req, res, next) => {
try {
// console.log("req.params.onecomment:",req.params.onecommentId);
const onecomment = await Comment.findOne({
where:{id: req.params.onecommentId},
include: [{
model: User,
attributes: ['id', 'nickname'],
}],
})
// console.log("onecomment:",JSON.stringify(onecomment));
res.status(200).json(onecomment);
} catch (error) {
console.error(error);
next(error);
}
});
if i get result data this will put draft.onecomment
(reducer/post.js)
case GETONECOMMENT_REQUEST:
draft.loadPostLoading = true;
draft.loadPostDone = false;
draft.loadPostError = null;
break;
case GETONECOMMENT_SUCCESS:
// console.log("action.data:::",action.data);
draft.loadPostLoading = false;
draft.onecomment = action.data;
draft.loadPostDone = true;
break;
case GETONECOMMENT_FAILURE:
draft.loadPostLoading = false;
draft.loadPostError = action.error;
break;
and i can get data in onecomment by using useselector at (NotifiCard.js)
const {onecomment} = useSelector((state) => state.post);
what i want is that when i press LookforReply i want to pass itemm data to
ReplyComment component but if i press LookforReply, i can't get itemm data
Immediately
(ReplyComment.js)
const ReplyComment = ({route}) => {
const {itemm} = route.params;
console.log("itemm",itemm);
return (
<Container>
<TodoListView parenteitem={itemm} />
<AddTodo item={itemm} />
</Container>
);
};
I think that the LookforReply function is executed asynchronously and navigate is executed before the onecomment data comes in, and it doesn't seem to be able to deliver the itemm.
so how can i fix my code?....
I have React Component in componentDidMount fetch data from the server. The issue is componentDidMount called twice also the API called twice. I have a view increment API like youtube video views increment twice in the database because of twice API calling.
class SingleVideoPlay extends React.Component {
constructor(props) {
super(props);
this.player = React.createRef();
}
state = {
autoPlay: true,
relatedVideos: [],
video: null,
user: null,
comments: [],
commentInput: {
value: '',
touch: false,
error: false
},
following: false,
tab: 'comments'
};
_Mounted = false;
componentDidMount() {
this._Mounted = true;
if (this._Mounted) {
const videoId = this.props.match.params.id;
this.getVideoDetails(videoId);
}
}
componentWillUnmount() {
this._Mounted = false;
try {
clearInterval(this.state.videoInterval);
this.props.videoEditUrl('');
} catch (error) {}
}
captureVideoTime = async () => {
const { video } = this.state;
const result = await updateWatchTime({
id: video._id,
time: 1
});
if (result.status === 200) {
const updateVideo = {
...video,
secondsWatched: video.secondsWatched + 1
};
this.setState({ video: updateVideo });
}
};
videoEnded = () => {
clearInterval(this.state.videoInterval);
};
videoPause = () => {
clearInterval(this.state.videoInterval);
};
loadVideo = () => {
clearInterval(this.state.videoInterval);
};
playingVideo = () => {
const interval = setInterval(this.captureVideoTime, 1000);
this.setState({ videoInterval: interval });
};
getVideoDetails = async (videoId) => {
const video = await getVideo(videoId);
if (video.status === 200) {
let response = video.data;
if (this.props.userId)
if (response.user._id === this.props.userId._id)
this.props.videoEditUrl(`/video/edit/${response.media._id}`);
this.setState({
relatedVideos: response.videos.docs,
video: response.media,
user: response.user
});
this.checkIsFollowing();
this.updateVideoStat(response.media._id);
}
};
updateVideoStat = async (id) => videoView(id);
checkIsFollowing = async () => {
const { userId } = this.props;
const { video } = this.state;
if (userId && video) {
const response = await isFollow({
follower: userId._id,
following: video._id
});
if (response) {
this.setState({ following: response.following });
}
}
};
addOrRemoveFollowing = async () => {
this.checkIsFollowing();
const { following, video } = this.state;
const { userId } = this.props;
if (userId) {
if (following) {
const response = await removeFollow({
follower: userId._id,
following: video._id
});
this.setState({ following: false });
} else {
const response = await addFollow({
follower: userId._id,
following: video._id
});
this.setState({ following: true });
}
}
};
submitCommentHandler = async (event) => {
const { userId } = this.props;
event.preventDefault();
if (userId) {
const result = await saveComment({
mediaId: this.state.video._id,
parentId: '0',
userID: userId._id,
userName: userId.username,
comment: this.state.commentInput.value
});
console.log(result);
if (result.status === 200) {
this.getVideoComments();
this.setState({ commentInput: { value: '', touch: false, error: false } });
}
}
};
render() {
const { autoPlay, relatedVideos, video, user, comments, commentInput, following, tab } = this.state;
const { userId } = this.props;
return (
<div className="container-fluid">
some coponents
</div>
);
}
}
const mapStateToProps = (state) => ({
userId: state.auth.user
});
export default connect(mapStateToProps, { videoEditUrl })(SingleVideoPlay);
I don't know why componentDidMount called two times alse it shows memmory lecage issue.
How to Fix it.
Multiple componentDidMount calls may be caused by using <React.StrictMode> around your component. After removing it double calls are gone.
This is intended behavior to help detect unexpected side effects. You can read more about it in the docs. It happens only in development environment, while in production componentDidMount is called only once even with <React.StrictMode>.
This was tested with React 18.1.0
I think the issue exists on the parent component that used SingleVideoPlay component. Probably that parent component caused SingleVideoPlay component rendered more than once.
Also, there is an issue on your code.
componentDidMount() {
this._Mounted = true;
if (this._Mounted) {
const videoId = this.props.match.params.id;
this.getVideoDetails(videoId);
}
}
Here, no need to check if this._Mounted, because it will always be true.
1.Install jQuery by
npm i jquery
import $ from 'jquery'
create your function or jwuery code after the export command or put at the end of the file