sportsBasketballChange another place its not setting state properly - javascript

I tried to say is I am not able to set the value using setState in sportsBasketballChange function but I am able to set it in sportsSoccerChange function
i am new to react.js
i am trying to set the value using setState.
in sportsSoccerChange function its correctly setting setState.
but sportsBasketballChange another place its not setting state properly.
can you guys tell me how to fix it.
providing my code below.
part of code
sportsSoccerChange(value) {
this.props.onChange();
let processedValue = value;
// sportsMessages sportsAirFalling
processedValue = sportsAirFallBALL(processedValue, this.props.sportsAirFall);
// sportsSuceessOnTime-ation
let sportsSuceessOnTime-ationResult = sportsSuceessOnTime-ateBALL(processedValue, this.props.sportsDrive);
if (sportsSuceessOnTime-ationResult === true) {
this.setState({ sportsOutcome: 'sportsSuceessOnTime-' });
///here i get value as sportsSuceessOnTime-
}
//this.setState({ isBALLValid: sportsSuceessOnTime-ationResult });
// formatting
processedValue = formatBALL(processedValue, this.props.sportsLongJump);
// set value in local component state
this.setState({ sportsMessagesValue: processedValue });
},
sportsBasketballChange() {
if (this.state.sportsOutcome === 'female') {
this.setState({ sportsOutcome: 'sportsSuceessOnTime-' });
///here i don't get value as sportsSuceessOnTime-
}
},
whole code here
https://gist.github.com/js08/e20c02bf21242201c1525577d55dedbc

I'm assuming that you are checking the value of this.state at those commented lines, either using logging or debugging.
setState is asynchronous. This means that there is no guarantee that the changes have occurred by the time you reach the next line of code. However, setState allows you to provide a callback function to be run after the state has finished updating. That is where you should be checking the updated value.
sportsBasketballChange() {
if (this.state.sportsOutcome === 'female') {
this.setState({ sportsOutcome: 'sportsSuceessOnTime-' },
function(){
console.log(this.state.sportsOutcome); // == 'sportsSuceessOnTime-'
}
);
console.log(this.state.sportsOutcome); // untrustworthy
}
},

Related

How to make props equal to state that does not exist yet?

Solved Thank you for your help
I am setting props of component
<Component myprops={state_variable}/>
The problem is that when I am creating the component and setting the props the state variable does not exist yet and my code breaks. What can I do to solve this problem? In addition when I change the state the prop is not updated.
<ServiceTicket
showOverlay={Tickets_disabled_withError[ticket_num]?.isDisabled}
showSelectedError={Tickets_disabled_withError[ticket_num]?.showError}
/>
My intial state initial variable:
const [Tickets_disabled_withError,setTickets_disabled_withError] = useState({})
I am trying to call function that will update state and change value that props is equal to.
const OverLayOnAll = (enable) =>
{
let tempobject = Tickets_disabled_withError
for (let key in tempobject)
{
if (enable == "true")
{
tempobject[key].isDisabled = true
}
else if (enable == "false")
{
tempobject[key].isDisabled = false
}
}
setTickets_disabled_withError(tempobject)
}
I fixed the issue. Thank you so much for your help. I had to set use optional chaining ?. and also re render the component.
The value exists. It's just that the value itself is undefined. You need to set an initial value when defining your state
const [statevariable, setstatevariable] = useState({
somekey: {
isDisabled: false // or whatever the initial value should be
}
}) // or whatever else you need it to be
For your second problem, you are using the same pointer. JavaScript does equality by reference. You've transformed the existing value, so React doesn't detect a change. The easiest way to fix this is to create a shallow copy before you start transforming
let tempobject = {...Tickets_disabled_withError}
Your question isn't very clear to me, but there's a problem in your setTickets_disabled_withError call.
When you update a state property (ticketsDisabledWithError) using its previous value, you need to use the callback argument.
(See https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous)
overlayAll = (enable)=> {
setTicketsDisabledWithError((ticketsDisabledWithError)=> {
return Object.keys(ticketsDisabledWithError).reduce((acc,key)=> {
acc[key].isDisabled = (enabled=="true");
return acc;
}, {}); // initial value of reduce acc is empty object
})
}
Also, please learn JS variable naming conventions. It'll help both you, and those who try to help you.

In React.js, how can I code the logic of aomw buttons considering that this.setState doesnt' update anything until it is passed into another function?

I am working on this so-called webpage and have several "tiles" arranged in a table-like form. When a tile is clicked and it is an image, it is supposed to be replaced by a <p> element, and when a tile is clicked and it is a paragraph, it is supposed to be replaced by an <img>. However, no two tiles can show <p> elements at the same time.
handleClickTile(e) {
const newTarget = e.target
// if (this.state.clickedTarget !== newTarget) {
// const stateClickedTgt = tgt
if(this.state.mode === 'p') {
if(newTarget !== this.state.clickedTarget) {
console.log("IS new target different from old? ")
this.setState({ mode: 'image' })
this.setState({ clickedTarget: newTarget})
} else {
this.setState({ mode: 'image' })
this.setState({ clickedTarget: newTarget })
}
}
// else {
// this.setState({ mode: 'p', clickedTarget: newTarget })
// }
if(this.state.mode === 'image') {
this.setState({ clickedTarget: newTarget, mode: 'p' })
// this.setState()
}
// }
// else {
// console.log("THE ELSE -- this.state.clicked is not newtgt ")
// this.state.mode === 'image'
// ? this.setState({ mode: 'p', clickedTarget: newTarget })
// : this.setState({ mode: 'image', clickedTarget: newTarget })
// }
}
As you can tell by the commenting and messy code, I have had several attempts at cracking the logic of this, but haven't gotten far. The problem I see is that this.setState() only updates anything once it is used in the render function, which is after handleClickTile() ends. This creates a problem in "resetting" the tiles so that no two tiles show <p> elements at the same time. At least, resetting the tiles to <img> when clicked is the approach I have taken, and I can't surmise any other ways, which is why I'm asking for help.
I would implement the componentDidUpdate() lifecycle method in your component class to compare the previous state with your current state after updating your state properties in handleClickTile().
When the condition that certain previous state properties and their corresponding current state properties don't match is met (i.e. this.state.mode or this.state.clickedTarget), then you can update the other state properties which will effectively "reset" your tiles.
So it would look something like:
componentDidUpdate(prevProps, prevState) {
if (prevState.mode !== this.state.mode) { // or replace mode with the appropriate state property to check for
this.setState({ stateProp: newValue }) // change whatever state properties you need to reset the other tiles
}
}
Here's more information on componentDidUpdate() from the React documentation.
You want to be sure to check that the appropriate state properties don't match between the previous and current state if you are going to set the state in this lifecycle method, in order to avoid an infinite loop (as mentioned in the documentation).

setState delay in react

I currently have a function in react native which does the following:
resetThenSet = (id, arrayId, title) => {
if(arrayId != 'selectProduct') {
// Setting state for each selected dropdown in selectedDropdowns
this.setState({
dataShowingToggle: true,
selectedDropdowns: {...this.state.selectedDropdowns, [arrayId]: title}
}, this.getProductCost(arrayId, id)
);
}
I run the above and I can confirm arrayId and title variables are valid and contain data. arrayId is also not 'selectProduct'. I added a console.log in there while debugging to ensure it runs, which it indeed does. The expected behavior I would expect is that the state is updated immediately.
However the selectedDropdowns isn't updated in state. When I add:
console.log(this.state) after the this.setState update there is no change. If I run the function twice it'll update on the second time it runs.
To test it even further I added static inputs like so:
this.setState({
dataShowingToggle: true,
selectedDropdowns: {...this.state.selectedDropdowns, testField: 'me here'}
}, this.getProductCost(arrayId, id)
);
console.log(this.state);
It only update state AFTER the first time it runs. Am I missing something?
UPDATE:
I updated the code to run the console.log on the call back to setstate:
if(arrayId != 'selectProduct') {
// Setting state for each selected dropdown in selectedDropdowns
console.log(arrayId + title);
console.log('i run');
this.setState({
dataShowingToggle: true,
selectedDropdowns: {...this.state.selectedDropdowns, [arrayId]: title}
}, console.log(this.state)
);
};
console.log is 'quantityProduct 25' for the arrayId + title
console.log(I run)
and then this state is NOT showing the quantityProduct 25
setState is asynchronous. This is why the function call has an optional callback.
I think you might have other issues.
Try putting that console log inside the callback function when you call setState to see when the state is updated with the values you gave it.

Reactjs: Checkbox state is update, then reverted when callback function terminates

I'm pretty new to react and I ran into a weird issue today. I have a function called handleCheckBoxClick()
handleCheckboxClick : function (e) {
this.setState({isChecked : e.target.checked},
function () {
if (this.state.isChecked) {
this.props.addToTransactionSubmissions(
this.props.submissionGuid,
this.props.paymentInfo
);
} else {
this.props.removeFromTransactionSubmissions(
this.props.submissionGuid
);
}
}
);
}
This particular function calls a function passed down through a parent called addTo/removeFromTransactionSubmission. The code for both is as follows:
addToTransactionSubmissions : function (guid, paymentInfo) {
if (Object.keys(this.state.transactionSubmissions).length === 0) {
this.setState({submissionType : paymentInfo.status_description.toLowerCase()},
function () {
console.log('it set the state though');
console.log(this.state.transactionSubmissions);
this.toggleButtons(this.state.submissionType);
}
);
}
var newTansactionSubmissions = update(this.state.transactionSubmissions,
{
$merge : {[guid] : paymentInfo}
});
this.setState({transactionSubmissions : newTansactionSubmissions},
function () {
console.log('state is now', this.state.transactionSubmissions);
}
);
},
removeFromTransactionSubmissions : function (guid) {
if (Object.keys(this.state.transactionSubmissions).length === 0) {
this.setState({submissionType : undefined},
function () {
this.toggleButtons(this.state.submissionType);
}
);
}
var newTransactionSubmission = update(this.state.transactionSubmissions,
{
[guid] : {$apply: function (x) {return undefined}}
});
this.setState({transactionSubmissions : newTransactionSubmission},
function () {
console.log('here in remove Transaction');
});
}
The problem I run into is that when addTo/removeFromTransactionSubmissions is called, the checkbox does not changes states, even though the state is changed before addTo/removeFromTransactionSubmissions is called. Through further debugging using Firebug, I discovered that 1) the functions are all being called properly, 2) if I do not set state in addTo/removeFromTransactionSubmissions everything runs without a hitch, and 3) the checkbox becomes unchecked after handleCheckboxClick completely finishes.
I suspect that for whatever reason, the state is being lost when Reactjs is trying to update the DOM. However, I do not know why this is the case and don't know how to further debug. And for clarification, the checkbox is in the child component whereas the transactionSubmissions state is in a parent, and on the click of a checkbox, transactionSubmissions is modified (Child Action modifies Parent state). If this is the wrong way to go about the problem, please tell me.
Basically what I want to do is every time I click/unclick a box, it removes the corresponding object to/from a map of ids to the object. Am I doing something incorrectly?
Thanks for the help!
I think you should use another aproach.
handleCheckboxClick : function (e) {
this.setState({isChecked : e.target.checked})
}
Add a method componentWillUpdate(https://facebook.github.io/react/docs/component-specs.html#updating-componentwillupdate) or componentDidUpdate(https://facebook.github.io/react/docs/component-specs.html#updating-componentdidupdate) and handle there the changes that must occur after state change
componentWillUpdate()
{
if (this.state.isChecked)
{
this.props.addToTransactionSubmissions(
this.props.submissionGuid,
this.props.paymentInfo);
} else {
this.props.removeFromTransactionSubmissions(this.props.submissionGuid);
}
}
Also you should not call setState sequencially, it can throw some errors by trying to mutate a component while it was updating.
Every time your code calls setState, react goes trought all the dom, check what has changed and render the changes again, saving processing. Ref:https://facebook.github.io/react/docs/component-api.html#setstate

Switching Values with chrome storage

I want to save a boolean value by clicking on a picture that changes its state from true to false every time I click onto the picture.
So simply I want to write something like
function SwitchByImage(propertyName) {
var oldValue=chrome.storage.sync.get({propertyName}, null);
var newValue=!oldValue;
chrome.storage.sync.set({propertyName:newValue},null);
if (newValue) {
$("#whateverimage").attr("src","upimage.jpg");
} else {
$("#whateverimage").attr("src","downimage.jpg");
}
}
I know that this does not work. Where I added "null" should be a function. My problem is: The storage works asynchronous, so it does not seem to be possible to write and read my data in a sequence.
What is the best way to get around this issue?
Since chrome.storage.sync.get is asynchronous, the fetched value will be available in the callback, so that is where the rest of the code should be placed:
function SwitchByImage(propertyName) {
chrome.storage.sync.get(propertyName, function(items) {
var oldValue = items[propertyName];
var newValue = !oldValue;
chrome.storage.sync.set({ propertyName: newValue });
if (newValue) {
$("#whateverimage").attr("src", "upimage.jpg");
} else {
$("#whateverimage").attr("src","downimage.jpg");
}
});
}

Categories

Resources