Google Recaptcha works only on page manual reload React - javascript

The issue with this is that apparently, Google V3 Recaptcha does not update the captchaCode, so it is required to manually reload the page each time to force this behavior. Are there any options I can programmatically force the Google V3 Recaptcha update? Here is the code, which unfortunately does not work. Possible functionality that might affect it:
Firebase auth presence
<div id="recaptcha-container" /> defined in HTML layout. Does it mean I have 2 Recaptchas on a website?
const submitSupportTicket = (e: any) => {
e.preventDefault();
recaptchaRef.current?.execute();
};
const onReCAPTCHAChange = async (captchaCode: any) => {
if (!captchaCode || !authUser) {
return;
}
try {
// Do something
} catch (error) {} finally {
recaptchaRef.current?.reset();
}
};
<ReCAPTCHA
size="invisible"
ref={ recaptchaRef }
sitekey={ process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY || '' }
onChange={ onReCAPTCHAChange }
/>

Related

Delay STATE change in React

I'm writing a website. It's a website that uses and fetches data from a stock API to displays stock prices and charts.
I have a search bar which changes state whenever a letter is typed in.. However, it's causing problems because it's instantly updating the state, which then fetches data from the API, and if for example I type in Z - then the API is instalty looking for a stock named "Z"
and the app crashes, goes blank ( because such link doesnt exist ). I literally have to copy the stock name like "AAPL" for example and then paste it - for the app to work properly.
var baseUrl = `https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=${search}&apikey=**********`;
because state of "search" is updated and it's searching for that stock/
Anyways, here's my stock search bar component.
const StockSearchBar = () => {
const { search, setSearch } = useContext(SearchContext); // i'm using context API to store state so I can access it across different components
const handleClick = (e) => {
if (setSearch !== '') { // if there's something in state, then post data to backend
const options =
{
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({search}),
};
const response = fetch(`http://localhost:3001/api/search`, options);
};
function handleButtonEvents(e) { // i'm using a function to chain handleClick() and setTimeout() to be run when button is clicked
e.preventDefault();
handleClick();
setTimeout(() => window.location.reload(), 3000); // delay the function for 3 seconds to give it time to fetch the data and display it, otherwise it might refresh the page without updating it with new data
}
const handleSearch = e => {
e.preventDefault();
setSearch(e.target.value.toUpperCase()); // i think the problem is here - i need to delay setting state
}
return (
<>
<div className="searchBar">
<label>Look for Stocks or Cryptos: </label>
<input type='text' onChange={handleSearch} onKeyPress={(ev) => {
if (ev.key === "Enter") { handleButtonEvents(); }}}
{/* search if Enter key is pressed */} // i think the problem is with **onChange** or the handleSearch **function** but not sure how to deal with it
placeholder={search} required />
<Button variant="success" type="submit" onClick={handleButtonEvents} >Search</Button>
</div>
<h1 className="src">{search}</h1>
{// display state to see if it's changing ( just testing }
</>
);
};
export default StockSearchBar;
Let me know if you want to see the context API file, or something else. But I think the probem is in the search bar component.
Thank you in advance for help.
you need to use Debounce in order to create a delay e.g. from lodash. so in your case it would be
const handleSearch = e => {
e.preventDefault();
debounce(setSearch(e.target.value.toUpperCase()), 500)// debounce 500 milliseconds
}

Why I am getting re-render errors on loading page?

I have created an app that consists of a loading screen. However, if the API is failed after 5 seconds, a failure message is to be conveyed. I am getting too-many re-renders error on the line which I have mentioned in the code below.
I have used setTimeout function to replace the message of failure if API fails after 5 seconds of loading the page. The rest of my app functionality is working fine.
My app code is: -
function App() {
//Is website loaded for first time?
const [loadingFirstTime, setLoadingFirstTime] = useState(true);
//Has the site loading failed? If yes, pass that to loading component
const [loadingFailed, setLoadingFailed] = useState(false);
//To be run first time the website is loaded
useEffect(() => {
getMovies()
.then(res => setMoviesDetails(res))
.then(() => setLoadingFirstTime(false));
}, [])
................... some code here .............
//If the details of api haven't been loaded or api loading failed
if (Object.keys(moviesDetails).length === 0 && loadingFirstTime) {
//------**Error occurs here after 5 seconds as per the console**-----------------
//check for the same thing after 5 seconds, if initial data still has been loaded?
setTimeout(() => {
if (Object.keys(moviesDetails).length === 0 && loadingFirstTime) {
setLoadingFailed(true);
}
}, 5000);
return (
<LoadingScreen status={loadingFailed} />
)
}
return (
<>
........ App components which are working fine .............
</>
);
}
Code for my loading component: -
function LoadingScreen({status}) {
const [loadingText, setLoadingText] = useState("Loading the site...");
//check if site loading failed and display appropiate message
if (status) {
setLoadingText("Website loading failed. Please reload or contact the administrator.");
}
return (
<div className="loading-screen">
<h1>{loadingText}</h1>
</div>
)
}
In React, you should avoid changing states when rendering, which is what you are doing in your LoadingScreen component when you are setting loadingText.
setLoadingText("Website loading failed. Please reload or contact the administrator.");
This is happening all the time you are passing a truthy value to status. That line is making LoadingScreen component to re-render itself again and again in an infinite loop.
Generally, it is better to implement this feature inside a useEffect function like this one:
function LoadingScreen({ status }) {
const [loadingText, setLoadingText] = useState("Loading the site...");
useEffect(() => {
if (status) {
const newLoadingText =
"Website loading failed. Please reload or contact the administrator.";
if (newLoadingText !== loadingText) {
// This state setter provokes a re-render so set only if new value is
// different than the actual value stored in state
setLoadingText(newLoadingText);
}
}
}, [loadingText, status]);
return (
<div className="loading-screen">
<h1>{loadingText}</h1>
</div>
);
}

How do I trigger a re-rendering of a block?

in a WordPress Gutenberg plugin
hooks_addFilter_editor_blockEdit = (BlockEdit) => {
return (props) => {
apiFetch({url: 'https://example.com/api/'+props.attributes.content
}).then(_return => {
props.attributes.content = _return;
// What should I use here to force re-render the block?
})
return ( <BlockEdit { ...props } /> );
}
}
wp.hooks.addFilter( 'editor.BlockEdit', 'my-plugin-slug', hooks_addFilter_editor_blockEdit );
For the above code, my plugin sends the props.attributes.content into an external API, and updates it asynchronously. Visually, as many default gutenberg blocks use props.attributes.content to display the content of the block (paragraph blocks for instance), that content gets updated on the editor, automatically, but not immediately. Re-rendering of the block happens only when my cursor gets off the block, or when I get the input focus out of this block.
What can I add to the above code to force the editor to visually show the updated content as soon as the apiFetch call has succeeded?
Try if this works for you:
hooks_addFilter_editor_blockEdit = (BlockEdit) => {
return (props) => {
// Destructure "props"
const { attributes, setAttributes } = props;
apiFetch({url: 'https://example.com/api/'+attributes.content
}).then(_return => {
// What should I use here to force re-render the block?
setAttributes( { content: _return } );
})
return ( <BlockEdit { ...props } /> );
}
}
wp.hooks.addFilter( 'editor.BlockEdit', 'my-plugin-slug', hooks_addFilter_editor_blockEdit );
Still, while typing in a block, there might be a slight delay until your api responds. Also maybe you need to wrap your BlockEdit in a HigherOrderComponent.

How to add an auth listener firebase without getting memory leak

need a little help.
i'm trying to add an auth listener to my react app, but i'm getting a memory leak, i need this listener to be active all the time so it will render the user content that is logged in, the login & register are on the same route as the user , on auth state change i am just rendering different components.
state = {
login: false
};
componentWillMount() {
this.authListener();
}
authListener = () => {
auth.onAuthStateChanged(user => {
if (user) {
this.setState({
login: true
});
} else this.setState({ login: false });
});
};
redirectOnLogIn = () => {
let { login } = this.state;
if (!login) {
return <Auth />;
} else {
return <Users />;
}
};
componentWillMount() - this function might end up being called multiple times before the initial render is called so might result in triggering multiple side-effects. Due to this fact it is not recommended to use this function for any side-effect causing operations. Try using componentDidMount() and report back.
P.S. also if I were you, I would move auth.onAuthStateChanged in your app.js file -- something like this
firebase.auth().onAuthStateChanged(user => {
if (user) {
ReactDOM.render(<Users />, document.getElementById("app"));
}
} else {
ReactDOM.render(<Auth />, document.getElementById("app"));
}
});
Also for initial run you could add something like this before it.
var user = firebase.auth().currentUser;
if(user){
...
}else{
...
}

How to navigate to another view on a Webview Event in React Native?

I am using react-native-webview-messaging to get event from a web view.
When the event is triggered i manage to change the state but I can not navigate to a new View.
This is what I do :
componentDidMount() {
const { messagesChannel } = this.webview;
messagesChannel.on('json', json => this.setState({
message: json,
}, () => {
return (
<GoToThisView />
);
}));
}
So my state changes to the JSON that I get from the webview but the return statement doesn't open a new page.
What am I doing wrong?
If you are using StackNavigator in your app then you can directly use navigate('screen_name') to navigate to the screen you want. Return is used with render.
componentDidMount() {
const { messagesChannel } = this.webview;
messagesChannel.on('json', json => this.setState({
message: json,
}, () => {
navigate('GoToThisView');
}));
}
The screen name 'GoToThisView' must have been defined .

Categories

Resources