how to get updated state value after updating in a function - reactjs

I'm trying to get login user detail. I need to put data to state and used the same state for further processing it takes time to put data to state and use this data. nearly it takes 2- 3 sec to use the state with that data.
I solved this issue if we use setTimeOut() function with 3 sec so that we it updates data in this time. if we don't use setTimeOut() and use state wright after updating it then it will provide initial data of the state.
complete_date = date + ":" + month + ":" + year;
var query = firebase.database().ref('attendence/'+ complete_date +"/").orderByKey();
email_match=false;
entry_time =null,
l_id = null,
query.on("value",(data)=>
{
data.forEach(function(childs)
{
l_id = childs.key;
// __ to check if the user already loged in before.
var att_query = firebase.database().ref('attendence/'+ complete_date +"/"+ l_id).orderByKey();
att_query.once("value",(data)=>
{
if(email == data.child('email').val())
{
email_match = true;
entry_time = data.child('timeEntry').val();
}
}); //
}); //
this.setState({ last_id:l_id });
this.setState({ emailMatchState:email_match });
this.setState({alreayLogedState : entry_time});
}); // _____end of query.on("value",(data)=>
setTimeout(() =>
{
console.log("-----------------------------------");
console.log("already logged :",this.state.alreayLogedState," email match :",this.state.emailMatchState , " result : ", this.state.result , " last_id :",st.last_id);
console.log("-----------------------------------");
},3000);
I need to use state after updating without the use of setTimeout() for faster working of the application.

The second argument for setState is a callback to execute when all updates are done
this.setState({ last_id:l_id }, () => console.log(this.state.last_id))

setState takes an optional second argument that gets called after the updates to the state object have taken place.
example:
let callback = () => {
// do something
}
this.setState({
keyToUpdate: valueToUpdate
}, callback)
Additional reading about the use of this callback:
https://medium.learnreact.com/setstate-takes-a-callback-1f71ad5d2296?gi=18aa91e88437
Also, unless something is happening in between the seperate calls, these:
this.setState({ last_id:l_id });
this.setState({ emailMatchState:email_match });
this.setState({alreayLogedState : entry_time});
can be simplified to this:
this.setState({
last_id:l_id,
emailMatchState: email_match,
alreayLogedState: entry_time
}); //optionally add callback

Related

AngualrJs: how to detect when user enters an invalid state in the brower's address bar?

Somewhat related : Angular - ui-router get previous state.
I have search results view. Obviously, it makes no sense for the user to enter this URL into the browser's address bar & navigate there.
I would like to detect if (s)he does so & issue an admonition.
But, how? If a user goes directly there, there is no state transition. So, how do I detect it?
When user enters url manually - your app is re-inited, so use app.run to track location:
app.module('myModule').run(['$location'], ($location) => {
if ($location.path().startsWith('/search')) {
alert('bad boy')
}
})
Or first state change to track state name:
app.module('myModule').run(['$transitions'], ($transitions) => {
const deregister = $transitions.onSuccess({}, (transition) => {
if (transition.to().name === 'search') {
alert('bad girl')
}
deregister();
})
})
I settled for a service, which I already use to share data between controllers , when changing state. The reason being that transition state change OnSuccess() does not work the first time, as per
https://github.com/angular-ui/ui-router/issues/3536 and may others
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=++=+=+=+=+=+=+=+=+=+=+=
Self.setState = function (currentState, newState) {
Self.setPreviousState(currentState);
console.log("Change state from [" + currentState + "] to [" + newState + "]");
Self.state = newState;
$state.go(newState);
}
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=++=+=+=+=+=+=+=+=+=+=+=
Self.getState = function () {
console.log("Current state is [" + Self.state) + "]";
return Self.state;
}
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
Self.getPreviousState = function () {
return Self.previousState;
}
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
Self.setPreviousState = function (previousState) {
Self.previousState = previousState;
}

Can not change state value before submitting in reactjs

I am using one of react phone input library and getting the value of phone number is in "+9901231231234" format . I want only last ten value is in integer form. So i am converting them in number.
if (this.validator.allValid()) {
const phnNo = this.state.phone // +9901231231234
if(phnNo.length>10){
var lastTen = phnNo.substr(phnNo.length - 10);
const subphone = Number(lastTen) //1231231234
this.setState({ phone: subphone }) // Now I want to set the this.state.phone = 1231231234
alert(this.state.phone) // +9901231231234
}
} else {
this.validator.showMessages();
// rerender to show messages for the first time
// you can use the autoForceUpdate option to do this automatically`
this.forceUpdate();
}
But I can not change the current state value with the new value i am generating.Thank you.
The setState function will not update your values synchronously, your state will not be changed right away. The second parameter of it allows you to give a callback function triggering when the state has been mutated :
this.setState({ phone: subphone }, () => { alert(this.state.phone) //1231231234 })

React state late update

i need to develop a simple tagging system. I do the following:
- on img click I store the click position
- next I open an input text
- on input change I query db with axios
- and so on till the db insert with the tags info
The problem is that the state that I update seems to be 1 turn in the past
imgSetTag(event){
this.getTagPosition(event)
.then( (response) => {
this.setState({
'imgTagsCoord' : response
}, console.log( 'imgTagsCoord then', this.state.imgTagsCoord ));
document.getElementById("imgTagInput").focus();
})
.catch( (err) => console.log(err) )
};
getTagPosition(event){
return new Promise(function(resolve, reject) {
var bounds = event.target.getBoundingClientRect();
var x = event.clientX - bounds.left;
var y = event.clientY - bounds.top;
console.log( {x: x, y: y} );
var tagCoord = { x : Math.round( x/bounds.width * 100 ), y : Math.round( y/bounds.height * 100 ) };
resolve(tagCoord);
});
}
The last try is splitting the function in two and wrapping the second in a promise but this.state.imgTagsCoord is always i round in the past.
The second argument of setState function should be a callback function. In your case, it should be written as follows:
() => console.log('imgTagsCoord then', this.state.imgTagsCoord )
When you pass in console.log('imgTagsCoord then', this.state.imgTagsCoord ) directly (instead of wrapping it in an anonymous function), you are passing the result of the function instead of the function itself. Therefore, you get the state value at the time when the function executes, which is one round prior to what you expect.
Try to change your setState to this:
this.setState({'imgTagsCoord' : response}, () => console.log( 'imgTagsCoord then', this.state.imgTagsCoord ));
You're executing the setState callback directly, you're not giving a function that React will call once the state has been set, but you're logging directly.
The setState callback is a function that React will execute, in your code you're giving the result of the console.log execution

Updating arrays in react component state

In the function below, I am trying to update the state of a react component; the animalMix item is an array. I take a copy, update it and then try to overwrite the original. I have checked that the new array (newAnimalsHeld) is updated correctly, but this is not reflected when i set animalMix in state equal to it.
The whole thing can be seen in context here:
https://codepen.io/timsig/pen/XVdbdo?editors=0010
Many thanks for any help.
removePair(){
console.log('Match!');
console.log(this.flipped);
let animalsHeld = [...this.state.animalMix];
let theMatch = this.flipped[0].props.animal;
let newAnimalsHeld = animalsHeld.map(function(animal){
if (animal.animal === theMatch) {
console.log('MATCH! Animal: ' + animal.animal + 'Match:' + theMatch);
return {};
}else{
return animal;
}
});
console.log('New Animals held: ', newAnimalsHeld);
this.setState({
animalMix: newAnimalsHeld,
doTurn: true
});
this.flipped = [];
console.log(this.state.doTurn, this.state.animalMix);
}
setState is an asynchronous function. However, you can print to console after state has updated in the following manner:
this.setState({
animalMix: newAnimalsHeld,
doTurn: true
},() => {console.log(this.state.doTurn, this.state.animalMix);});

jest enzyme reactJS - method executes regardless of return

I have the following method I want to test:
handleDayClick(e, day, {disabled}) {
if (disabled) {
// Do not update the state if the day is disabled
return;
}
this.setState({ selectedDay: day });
this.props.dateClick(day);
};
So I wrote a mock function, passed it as a prop and figured I would test state and if the function gets called:
it('handleDayClick() should NOT set state.selectedDay, call props.dateClick when disabled', () => {
let mockDateClick = jest.fn();
const sidebar = shallow(<Sidebar dateClick={mockDateClick}/>);
let e = 'whatever';
let day = 'tomorrow';
sidebar.instance().handleDayClick(e, day, true);
expect(sidebar.state().selectedDay).toBe(undefined);
expect(mockDateClick).toNotHaveBeenCalled();
});
The thing is that the state().selectedDay gets set to tomorrow. The value before calling the method is 2017-01-12T18:18:13.216Z, so I am pretty sure the method does not exit on the render function.
What am I doing wrong?
In your test, you are doing: sidebar.instance().handleDayClick(e, day, true);
while handleDayClick is destructuring an object with the disabled key
handleDayClick(e, day, {disabled}) {
}
Try to call it like this : sidebar.instance().handleDayClick(e, day, { disabled: true });
In the future you might want to use tools like Flow to prevent errors https://flowtype.org/docs/react.html
you would have been able to detect it earlier by doing something like this :
handleDayClick(e: {}, day: string, {disabled}: boolean) {
}

Resources