sync button state in realtime using APIs in React Js - javascript

So I have two APIs one is Post API Which I linked to my Toggle button, whenever button is clicked it sends 1 or 0 value to Post API and I have other GET API from where I'm getting the state of value which I'm using to the same button to check weather it is 0 or 1.
The problem is my code works but it can't get sync because when I click button it updates state value through post API but previous GET Request Makes it again on previous state. so on render button flickers a couple of times and then get settled. Code is given below. Any solution will be highly appreciated. Thanks in advance.
P.S. on componentDidMount() I'm Calling the GET Request and handleChange is linked to the button
class Test extends React. Component {
constructor(props) {
super(props);
this. State = {
checked: false,
value:bool,
}
this.handleChange = this.handleChange.bind(this);
}
componentDidMount() {
this.intervalId = setInterval(()=> this.loadData(), 1000);
this.loadData();
}
componentWillUnmount() {
clearInterval(this.intervalId);
}
async loadData() {
const headers = {
'api-key': 'key',
};
try {
const response = await fetch('url', { headers })
const json = await response.json();
const valueUp = json.data ;
if( valueUp ===1 ) {
this.setState({value: valueUp, checked: true})
}
else if (valueUp === 0) {
this.setState({value: valueUp, checked: false})
}
}
catch (err){ console.log(err);}
}
handleChange() {
if (this.state.value === 0) {
this.setState({ value:1, checked: true }, () => {
this.afterSetStateFinished();
})
}
else if (this.state.value === 1) {
this.setState({ value:0, checked: false }, () => {
this.afterSetStateFinished();
})
}
};
afterSetStateFinished(){
const article = {
"body": this.state.value
}
const headers = {
'api-key': 'key',
};
axios.post('url', article, { headers })
.then(function(response) {console.log(response);
})
}

Related

why componentdidmount called two times

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

window.location.reload is refreshing page again and again

I am working on project where I am invalidating browser cache but when I call this function window.location.reload() it refresh page again and again . I want to reload page at once . Could someone please help me how to stop page from refreshing again and again . Thanks
Note: I am using React.JS
Code
import React from "react";
import packageJson from "../package.json";
global.appVersion = packageJson.version;
// version from response - first param, local version second param
const semverGreaterThan = (versionA, versionB) => {
const versionsA = versionA.split(/\./g);
const versionsB = versionB.split(/\./g);
while (versionsA.length || versionsB.length) {
const a = Number(versionsA.shift());
const b = Number(versionsB.shift());
// eslint-disable-next-line no-continue
if (a === b) continue;
// eslint-disable-next-line no-restricted-globals
return a > b || isNaN(b);
}
return false;
};
class CacheBuster extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: true,
isLatestVersion: false,
refreshCacheAndReload: (caches) => {
if (caches) {
caches.keys().then(async function (names) {
await Promise.all(names.map((name) => caches.delete(name)));
});
}
window.location.reload();
},
};
}
componentDidMount() {
fetch(`/meta.json?${new Date().getTime()}`, { cache: "no-cache" })
.then((response) => response.json())
.then((meta) => {
const latestVersion = meta.version;
const currentVersion = global.appVersion;
const shouldForceRefresh = semverGreaterThan(
latestVersion,
currentVersion
);
if (shouldForceRefresh) {
console.log(
`We have a new version - ${latestVersion}. Should force refresh`
);
this.setState({ loading: false, isLatestVersion: false });
} else {
console.log(
`You already have the latest version - ${latestVersion}. No cache refresh needed.`
);
this.setState({ loading: false, isLatestVersion: true });
}
});
}
render() {
const { loading, isLatestVersion, refreshCacheAndReload } = this.state;
return this.props.children({
loading,
isLatestVersion,
refreshCacheAndReload,
});
}
}
export default CacheBuster;
if (caches) {...} else (window.location.reload(true));
This code is struck between constructor and the render.
this.state.refreshCacheAndReload should be set to null in constructor, where in you choose to reload it in componentdidmount whenever the version mismatches.

Checkbox with true or false value throwing error in React Class Component?

I have two checkboxes that were working previously but are now throwing an error. These checkboxes simply return a true or false in the form, which is submitted to the Firestore backend. These were working fine recently until so other changes were make.
The error in question is
TypeError: Cannot create property 'cash' on boolean 'false'
This is triggered whenever the checkbox is clicked. I am using a
changeStoreData() action to update the FireStore, this action is called all throughout my app in order to update the users information
This is my state setup
constructor(props) {
super(props);
this.state = {
currency: "USD",
tax_rate: "8.00",
prices_include_tax: false,
payment_types: {
cash: false,
credit: false
}
};
}
Theses are the buttons in question
handleCash = () => {
this.setState(state => {
var newData = state.payment_types;
newData.cash = !state.payment_types.cash;
return {
payment_types: newData
};
});
};
handleCredit = () => {
this.setState(state => {
var newData = state.payment_types;
newData.credit = !state.payment_types.credit;
return {
payment_types: newData
};
});
};
This is the onSubmit function calling the changeStoreData() function
handlePaymentInfoSub = e => {
e.preventDefault();
this.setState(state => {
changeStoreData(state);
// I know this needs to be more explicit
// Other places in my app this is called changeStoreData({DBvalue:
// stateValue}) but I am not sure how to do this with nested values
return state;
});
};
and finally here is the changeStore function itself from the actions file
export function changeStoreData(data) {
let currentState = store.getState();
let id = currentState.currentStore.id;
console.log(data);
firestoreDb
.collection("users")
.doc(currentState.uid)
.collection("stores")
.doc(id)
.update(data)
.then(
store.dispatch({
type: UPDATE_STORE_DATA,
data: data
})
)
.catch(err => {
console.log(err);
});
}
The error given is
TypeError: Cannot create property 'cash' on boolean 'false'

AsyncStorage & Drawer render always null

I have a login screen with a button remember me and when I connect, I would like to store this info in asynsctorage like this:
if (this.isFormValid()) {
AccountService.login(login, password)
.promise.then(body => {
console.log('onLoginClick -> body', body)
Keyboard.dismiss()
AsyncStorage.setItem('login', login)
if (this.state.isRememberMeSelected) {
console.log("i'm in the storage !")
AsyncStorage.multiSet([['login', login], ['password',
password], ['isRememberMeSelected', '1']])
} else {
AsyncStorage.multiSet([['login', ''][('password', '')],
['isRememberMeSelected', '0']])
}
when I go back to my Drawer, I try to read the storage and get my value "isRememberMeSelected" :
async componentDidMount() {
// await AsyncStorage.getItem('login').then(value => {
// console.log('DrawerLogin', value)
// //this.setState({login: value})
// })
// await AsyncStorage.getItem('password').then(value => {
// console.log('DrawerPassword', value)
// //this.setState({password: value})
// })
await AsyncStorage.getItem('isRememberMeSelected').then(value => {
console.log('DrawerIsRememberMeSelected', value)
this.setState({isRememberMeSelected: value})
})
// await AsyncStorage.getAllKeys((err, keys) => {
// console.log(' Allkeys', keys)
// })
}
in me drawer, I check the value "isRememberMeSelected" to remove some items:
StorageMultiRemove = async () => {
try {
await AsyncStorage.multiRemove(['refreshToken',
'stripeCustomerId', 'token'], err => {
console.log(' Dans multiRemove Error', err)
})
} catch (error) {
// Error saving data
}
}
isRememberMeSelected === '1' ? this.StorageMultiRemove() :
AsyncStorage.clear()
when I go back in my drawer, this value and always null EXCEPT if I leave the app and relaunch ... there everything is well set....
I fit well in my condition (the one before doing my setItem) ...
I would like to record this data in asynStorage, return to my drawer and have these values ​​available
You could add a variable that will change when asyncstorage has been fetched
class Myform extends React.Component {
state = {
loading: true
}
then in component did mount update the state
componentDidMount() {
await AsyncStorage.getItem('isRememberMeSelected').then(value => {
console.log('DrawerIsRememberMeSelected', value)
this.setState({
isRememberMeSelected: value,
loading: false
})
})
}
and in render
render() {
if(loading) return; // could return loading spinner or something
}

Getting backend data in front reactJS

I am getting data from the backend to display it in the font like this
componentDidMount() {
const response = this.props.store.privateImputationData;
console.log(response);
}
It displays null in the console, now if i do a setTimeout it works!
componentDidMount() {
setTimeOut(() => {
const response = this.props.store.privateImputationData;
console.log(response);
}, 500);
}
This how i m getting data from my store:
#computed get ImputationData() {
return this.privateImputationData || {};
}
loadImputation = (diplayedImputations) => {
HttpClient.postJSON(this.apiDataUrl, diplayedImputations).then((result) => {
this.privateImputationData = result;
this.loadAdditionalData();
});
}
How can i do it without setTimeout?
You can use the state object: State and Lifecycle. Whenever the state changes, whatever component uses it, get's updated too.
this.state = {privateImputationData: null} //or some default
So in your code:
#computed get ImputationData() {
return this.privateImputationData || {};
}
loadImputation = (diplayedImputations) => {
HttpClient.postJSON(this.apiDataUrl, diplayedImputations).then((result) => {
this.setState({privateImputationData: result});
this.loadAdditionalData();
});
}
To use the value:
this.state.privateImputationData;

Categories

Resources