setState not working with Switch block - javascript

I'm trying to build a little chat bot, and I seem to be nearing completion if it were not for this bug. The issue seems to be that my switch statement isn't handling the setState properly.
Uquestion extends React.Component {
constructor(props) {
super(props);
this.state = {
text: this.props.text,
response: "Here is the answer"
}
this.handleChange = this.handleChange.bind(this)
this.key = this.key.bind(this)
this.fetchResponse = this.fetchResponse.bind(this)
}
handleChange(event) {
this.setState({
question: event.target.value
})
}
fetchResponse() {
switch(this.state.searchKey) {
case "BBQ":
this.setState({
response:"Texas BBQ"
})
break;
case "book":
this.setState({
response:"It's close, but probably The Night in Question by Tobias Wolff."
})
break;
case "restaurant":
this.setState({
response:"Andaman, a little Thai spot in Denton, Texas."
})
break;
case "work":
this.setState({
response:"Lots of this and lots of that."
})
break;
case "upbringing":
this.setState({
response:"Texas thunderstorms over endless plains."
})
break;
case "future":
this.setState({
response:"I hope to work on meaningful applications and write meaningful narratives"
})
break;
case "fun":
this.setState({
response:"When the moon is full, I write by candle light."
})
break;
default:
this.setState({
response:"Um, what?"
})
}
}
//this function sets a key that I will later use to fetch a response to the user's question.
key() {
var question=this.state.question;
var questionUpper=question.toUpperCase();
// the is not -1 determines if the phrase appears anywhere in the question.
if(questionUpper.search("FAVORITE FOOD")!==-1) {
this.setState({
searchKey:"BBQ"
}, this.fetchResponse())
}
else if(questionUpper.search("FAVORITE BOOK")!==-1) {
this.setState({
searchKey:"Book"
}, this.fetchResponse())
}
else if(questionUpper.search("FAVORITE RESTAURANT")!==-1) {
this.setState({
searchKey:"Restaurant"
},this.fetchResponse())
}
else if(questionUpper.search("WORK EXPERIENCE")!==-1) {
this.setState({
searchKey:"work"
},this.fetchResponse())
}
else if(questionUpper.search("GROWING UP")!==-1) {
this.setState({
searchKey:"upbringing"
},this.fetchResponse())
}
else if(questionUpper.search("FAVORITE AUTHOR")!==-1) {
this.setState({
searchKey:"author"
},this.fetchResponse())
}
else if(questionUpper.search("FUTURE")!==-1) {
this.setState({
searchKey:"future"
},this.fetchResponse())
}
else if (questionUpper.search("FOR FUN")!==-1) {
this.setState({
searchKey:"fun"
},this.fetchResponse())
}
else {
this.setState({
searchKey:"default"
}, this.fetchResponse())
}
}
render() {
return (
<div>
<p> {this.state.response} </p>
<textarea onChange = {this.handleChange} className="q"> {this.props.text} </textarea>
<button className="a" onClick={this.key}>Ask!</button>
</div>
);
}
}
ReactDOM.render(<Uquestion text="Type Question Here."/>, document.getElementById("content"))

You are passing wrong callback in setState function. And in fetchResponse you've wrote some wrong cases. I've corrected your mistakes, you can see on working example in Codepen
wrong:
this.setState({
searchKey: "book"
}, this.fetchResponse())
correct:
this.setState({
searchKey: "book"
}, this.fetchResponse)

you can read react source code
ReactComponent.prototype.setState = function (partialState, callback){
!(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'setState(...): takes an object of state variables to update or a function which returns an object of state variables.') : _prodInvariant('85') : void 0;
this.updater.enqueueSetState(this, partialState);
if (callback) {
this.updater.enqueueCallback(this, callback, 'setState');
}
};
enqueueCallback: function (publicInstance, callback, callerName) {
ReactUpdateQueue.validateCallback(callback, callerName);
var internalInstance = getInternalInstanceReadyForUpdate(publicInstance);
if (!internalInstance) {
return null;
}
if (internalInstance._pendingCallbacks) {
internalInstance._pendingCallbacks.push(callback);
} else {
internalInstance._pendingCallbacks = [callback];
}
enqueueUpdate(internalInstance);
}
function enqueueUpdate(internalInstance) {
ReactUpdates.enqueueUpdate(internalInstance);
}
so, I think you the callback is like this:
this.setState({
searchKey:"BBQ"
}, this.fetchResponse)

Related

Update state for function that relies on if statement in ReactJs

Is it the best way to write the code below or i have to do better!
toggleListen() {
if (recognition !== null) {
this.setState({
listening: !this.state.listening
}, this.handleListen)
} else {
this.setState({
microAvailable: !this.state.microAvailable
}, this.handleListen)
}
}
Yes, you can conditionally set the listening or microAvailable properties depend on recognition !== null
function toggleListen() {
this.setState(
{
...(recognition !== null
? {
listening: !this.state.listening,
}
: {
microAvailable: !this.state.microAvailable,
}),
},
this.handleListen
);
}

React Redux functional component updating state not working

My data looks like this:
{
'004': [
{
year_week: '2020-W1',
actual_bank_amount: '6500000',
ext_in_rental_income: '',
ext_in_tax_refund: '',
ext_in_dividends_income: ''
},
{
year_week: '2020-W2',
actual_bank_amount: '6500000',
ext_in_rental_income: '',
ext_in_tax_refund: '',
ext_in_dividends_income: ''
}
],
'007': [
{
year_week: '2020-W22',
actual_bank_amount: '65050000',
ext_in_rental_income: '30000',
ext_in_tax_refund: '',
ext_in_dividends_income: ''
}
]
},
I am trying to update say date for year_week '2020-W1' in '004'.
No problem with action and reducer but data is not updated in the list.
Below is my reducer:
case 'UPDATE':
state.planningData[action.payload.currentSite].map((item, index) => {
if (item.year_week === action.payload.data.year_week) {
return Object.assign({}, item, action.payload.data);
}
return item;
});
console.log(state)
return {
loading: true,
planningData: state.planningData,
error: ''
}
What I am doing wrong please. Btw when I do console log or run redux extension I see the updated state.
Below is my action creator:
export const update = (data) =>
(dispatch, getState) => {
console.log("Update action called" + JSON.stringify(data))
const currentSite = getState().sites.currentSite;
dispatch({
type: 'UPDATE',
payload: {
data: data,
currentSite: currentSite
}
});
};
btw I am calling it from a editable cell component on "enter" and blur event below is my code
const save = async e => {
try {
const values = await form.validateFields();
toggleEdit();
dispatch(update({ ...record, ...values }));
} catch (errInfo) {
console.log('Save failed:', errInfo);
}
};
This isn't pretty but it works. You had a bit of nested data in your state and it wasn't being updated properly.
case "UPDATE":
let updatedPlanningData = {};
for (let prop in state.planningData) {
if (prop === action.payload.currentSite) {
updatedPlanningData[action.payload.currentSite] = state.planningData[
action.payload.currentSite
].map((item, index) => {
if (item["year_week"] === action.payload.data.year_week) {
return Object.assign({}, item, action.payload.data);
}
return item;
});
} else {
updatedPlanningData.prop = state.planningData[prop];
}
}
return {
loading: true,
planningData: updatedPlanningData,
error: ""
};
Here is example code in codesandbox
Edit: more compact solution
let updatedPlanningData = {...state.planningData};
updatedPlanningData[action.payload.currentSite].map((item, index) => {
if (item["year_week"] === action.payload.data.year_week) {
return Object.assign(item, action.payload.data);
}
return item;
});

Dynamic state is not getting updated in react

I am new to react js , here
this.state = {
technologies: [],
showLowError: false,
showHighError: false,
showMediumError: false
}
I have this state variables.
Now,
What I am trying to do is ,
if(type === "Low") {
errorState = "showLowError";
} else if(type === "Medium") {
errorState = "showMediumError";
} else {
errorState = "showHighError";
}
if (tobeupdated === "count") {
let validateData = this.validate(type, noc);
console.log("validateData is ==>", validateData);
this.setState({
[errorState]: validateData
})
}
update the state, depend upon some variables, Now,
[errorState] is not updating the exact value, Value for the state is not getting set.can any one help me with this ?
try adding:
this.setState(this.state);
after:
this.setState({
[errorState]: validateData
})

Why doesn't this change my redux state?

I have an array of array of objects in my state.
What I want to do is find the question with the correct id, then find the answer with the correct id to change it's value and update it to the state.
Here is what I got:
function updateObject(oldObject, newValues) {
return Object.assign({}, oldObject, newValues);
}
function updateItemInArray(array, questionId,answerId, updateItemCallback) {
const getQuestion = array.map(item => {
if(item.id !== questionId) {
return item;
}
})
const updatedItem = getQuestion[0].answers.map(answer => {
if(answer.id !== answerId) {
return answer;
}
​
const updatedItem = updateItemCallback(answer);
return updatedItem;
});
​
return updatedItems;
}
export function answerUpdate(state = [], action){
switch(action.type){
case 'ANSWER_UPDATE_FETCH_SUCCESS': {
const newAnswer = updateItemInArray(state.project, action.questionId, action.answerId, answer => {
return updateObject(answer, {value : action.newValue});
});
}
}
}
the object I'm looking through is kinda obvious but it looks something like this
project = [
question = {
id:"some Id",
answers: [
{
id:"another id",
value="someValue"
}
]
}
]
and some other properties but it is unrelevant for this question.
Thankful for every answer!
You need to update data in map itself instead of creating variable, map function returns new array with updated value and you are updating 0th index of array which won't be one you're looking for.
function updateItemInArray(array, questionId,answerId, newValue) {
return array.map(item => {
if(item.id !== questionId) {
return item;
} else {
item.answers.map(answer => {
if(answer.id !== answerId) {
return answer;
} else {
updateObject(answer, { value : newValue})
}
});
}
});
}
export function answerUpdate(state = [], action){
switch(action.type){
case 'ANSWER_UPDATE_FETCH_SUCCESS': {
return updateItemInArray(state, action.questionId, action.answerId, action.newValue);
}
}
}

reactjs - having some issues with my functions to update state and using promises

basically, I am validating form fields by checking if they pass my regex, and if they do, I am setting state with either 'success' or 'error' (used by react-bootstrap).
so basically, I have about 6 functions that need to execute, however, the password field validation functions are giving me a lot of trouble.
My handleSubmit() at the moment looks something like this -
handleSubmit() {
this.validate1();
this.validate2();
// ...
this.validatePassword();
this.validateConfirmPassword();
}
However, the issue is that validatePassword() will setState either 'success' or 'error', and since the functions are not firing off in order, I usually get the wrong result for validateConfirmPassword().
I am reading the mozilla page on Promises, but I am really confused and not sure how to apply that in my code.
Could I do something like Promise.all([everything_except_validateConfirmPassword]).then(validateConfirmPassword()) but that doesn't seem right..
validatePassword(pass) {
if (pass.length >= 8) {
if (checkPass.test(pass)) {
this.setState({
passValidation: validation.success
});
} else {
this.setState({
passValidation: validation.error
});
}
} else {
this.setState({
passValidation: validation.error
});
}
}
validateConfirmPassword(pass, confirmPass) {
const matches = pass === confirmPass;
if (matches && this.state.passValidation === validation.success) {
this.setState({
confirmPassValidation: validation.success
});
} else {
this.setState({
confirmPassValidation: validation.error
});
}
}
You can solve this by using React's componentDidUpdate in this way:
componentDidUpdate() {
if (this.state.canCheckConfirmPwd) {
this.validateConfirmPassword();
}
}
validatePassword(pass) {
if (pass.length >= 8) {
if (checkPass.test(pass)) {
this.setState({
passValidation: validation.success,
canCheckConfirmPwd: true, // on next update we'll trigger validateConfirmPassword()
});
} else {
this.setState({
passValidation: validation.error
});
}
} else {
this.setState({
passValidation: validation.error
});
}
}
validateConfirmPassword(pass, confirmPass) {
const matches = pass === confirmPass;
if (matches && this.state.passValidation === validation.success) {
this.setState({
confirmPassValidation: validation.success,
canCheckConfirmPwd: false, // to avoid retriggering the function on next update
});
} else {
this.setState({
confirmPassValidation: validation.error,
canCheckConfirmPwd: false,
});
}
}

Categories