Not able to change state on event trigger in react native - javascript

I am calling an event on react-native-voice to recognize the speech and calling an API and setting the state. But when I am setting a new value to a state array the array only have the new value instead of having the previous value. This is my code
constructor(props){
super(props);
this.state = {
results = [];
}
Voice.onSpeechResults = this.onSpeechResults;
}
and I have a event which is been triggered to call an API like this.
onSpeechResults = e => {
this._startRecognizing();
//var joined = this.state.results.concat();
getProductListingService(e.value[0]).then(data=>{
let demoVar = Object.values(data);
var newArray = this.state.results;
newArray.push(demoVar[1]);
this.setState({
results:newArray
})
this.setState({
show:true
});
});
};
But when setting the state I am only able to get the new element been pushed into the array instead of the previous state. I have tried using concat, spread, and setting a new array. Stuck, Please help. :(

First declare your state like:
this.state = {
results: []; // Don't use = for properties
}
second notice that if you setState() with same values that it already has, it doesn't set the state(and call render function).

Related

How to update or add an array in react.js?

I'm using react native and my component is based on class base function. I'm facing difficulty in updating or adding object in an array..
My case :
I have an array:
this.state = {
dayDeatil:[]
}
now i want to add an obj in it but before that i want check if that object exist or not.
obj = { partition :1, day:"sunday","start_time","close_time",full_day:false}
in condition i will check partition and day if they both not match. then add an object if exist then update.
here is function in which i'm trying to do that thing.
setTimeFunc =(time)=>{
try{
console.log("time.stringify() ")
let obj = {
partition:this.state.activePartition,
day:this.state.selectedDay.name,
full_day:false,
start_time:this.state.key==="start_time"?time.toString():null
close_time:this.state.key==="close_time"?time.toString():null
}
let day = this.state.dayDetails.filter((item)=>item.day===obj.day&&item.partition===obj.partition)
if (day.length!==0) {
day[this.state.key]=time.toString()
this.setState({...this.state.dayDetail,day})
} else {
console.log("2")
this.setState({
dayDetails: [...this.state.dayDetails, obj]
})
}
this.setState({ ...this.state, clockVisiblity: false });
}
catch(e){
console.log("error -> ",e)
}
}
To check if the object exists or not, you can use Array.find() method, if it doesn't exists, the method will return undefined.
Now to update the state, the easier way would be to create a new array and set it as the new dayDetails state like this:
const { dayDetails } = this.state;
dayDetails.push(newData);
this.setState({ dayDetails: [...dayDetails] })
You should use the spread operator when setting the state because React uses shallow comparision when comparing states for a component update, so when you do [...dayDetails] you're creating a new reference for the array that will be on the state, and when React compares the oldArray === newArray, it will change the UI.
Also, after your else statement, you're updating the state with the state itself, it's good to remember that React state updates are asynchronous, so they won't be availabe right after the setState function call, this may be causing you bugs too.

State value goes empty to child component

I'm trying to send information from parent to child component with a state.
In the parent component, I'm getting the value and storing it inside an array named valueArray. Later on, this array will be stored in a state and sent through child component to map and display the values.
1-) Function below takes the values selected by user and pushes them inside an empty array valueArray.
let valueArray = [];
const getSelectedItem = (event) =>{
if(valueArray.includes(item)){
valueArray.splice(item.index,1);
}else{
valueArray.push(item);
}
}
2-) In here, after user done with selecting values, another function to store values in state will be initiated by onClick, this function uses valueArray as argument.
<button onClick={() => handleState(valueArray)}>Buton</button>
3-) After the button click, handleState function executes and updates state with the elements in valueArray, values array goes to child component to map and perform display.
const [values,setValues] = useState([]);
const handleState = (arr) =>{
setValues([...arr])
}
Major problem in here is, when button clicked at the first time after selection, state becomes empty array and child component can't execute mapping because valueArray's initial value is []. Second click works and state changes with values inside the valueArray.
Use State like this.
const [valueArray, setValueArray] = [];
const getSelectedItem = (event) =>{
const array = [...valueArray];
if(array.includes(item)){
array.splice(item.index, 1);
// setValueArray([...valueArray.filter((ite) => ite != item)]);
setValueArray([...array]);
}else{
// valueArray.push(item);
setValueArray([...array, item]); // instead of push we should use spread or concat()
}
}

How can I create a reusable function that will setState for a variable object property?

I have an onChange function to update the state on all of my form inputs. The state I'm trying to update here is nested in an array as an object, but I am unsure how I can make a reusable function that will update the specific object property depending on which form input is changed.
Here's my function:
onChangeHandler = (e, index) => {
let currentStateObject = [...this.state.fundGroups]; //copying the current state
// This works, but I don't want allocationName to be hardcoded.
// How can I pass in a variable that relates to the specific property
// based on which input field is changed?
currentStateObject[index].allocationName = e.target.value;
this.setState({
currentStateObject
});
}
Here is what I have attempted but it does not work and breaks my code with an invalid token message:
currentStateObject[index].[e.target.name] = e.target.
I attempted this because in my input field, I added name="allocationName"
Does anyone know if I'm close to solving this? I'm very new to React. Thank you.
you almost got it. simply remove the . between [index] and [e.target.name] like:
currentStateObject[index][e.target.name] = e.target.value;
here is some example of state manipilation
state = {
random: [],
counter: 1
}
stateHandler = (e)=>{
let oldrandom = [...this.state.random]
oldrandom[e.target.name] = e.target.value;
this.setState({random:oldrandom })
}
manipulate state with a functional approach
stateHandler = ()=>{
this.setState((state,props)=>{
counter: state.counter+props.increment
})
}
You can simply:
onChangeHandler(event) {
this.setState({ [event.target.name]: event.target.value })
}

How to relocate Moment variables to state from render

I'd like to know how I can better store the variables I am using for moment in my react component.
I've already tried just declaring the variables in the constructor below the setState, but these variables are not changeable. I then tried to store the variables in the state, as key value pairs but since one of the values is dependent on another, it did not work.
Here is my current constructor:
constructor(props) {
super(props);
this.state = {
scooter: props.scooter,
header: props.header,
reservation: ""
};
}
componentWillReceiveProps(nextProps) {
this.setState({
scooter: nextProps.scooter,
header: nextProps.header
});
}
Some items will have to be called as well in componentsWillRecieveProps as the item will change with next props.
variables below
render() {
const reservation = this.state.scooter.state.LastAdminReservation;
var a = moment();
const c = moment(reservation.PendingDate);
const d = moment(reservation.EndDate);
const duration = d.from(c, true);
var timeSince = a.from(d, true);
const date = moment(reservation.DownloadAckDate).format("DD.MM.YYYY
HH:mm");
I'd like to be able to call these variables in my return and have var a and var timeSince be updated on next props while not storing them in my render as this is bad practice. Thanks!
You can do like this (putting in the state only variable that will be used inside other methods.
constructor() {
super();
const a = moment();
const c = moment(new Date());
const d = moment(new Date());
const duration = d.from(c, true);
const timeSince = a.from(d, true);
this.state = {
name: 'React',
timeSince
};
}
Try your best not to derive state from props. However, if you really need to, getDerivedStateFromProps is a safer method introduced in React 16.
componentWillReceiveProps is a deprecated method that you should be avoiding.
Instead, you can create a function that will return the date you need, and call it from your render method. If you are worried with performance, you can memoize that function. Example here
If you are using a state management solution like Redux, you can also move that logic up to a selector and pass down only the data you need into your component.

ReactJs: How to update property of state

I am trying to update the isSelected property for a row of my data stored in the state, the property doesn't update can anyone please tell me the best way to do this?
var selectedIdsPush = [];
var selectedIdsPush = this.state.contacts.slice();
for(var i=0;i<selectedIdsPush.length;i++)
{
var idAsNumber = parseInt(id);
if (page.state.contacts[i].id === idAsNumber) {
page.state.contacts[i].isSelected = true;
break;
}
}
Reacts wants consumers to setState instead of assigning properties directly. In this example, we could build and assign a new contacts list using:
var idAsNumber = parseInt(id);
var newContacts = this.state.contacts.map(function (contact) {
if (contact.id === idAsNumber) {
contact.isSelected = true;
}
return contact;
});
this.setState({ contacts: newContacts });
The property probably does get updated, but it won't be reflected in the UI as your app isn't re-rendered.
You could call this.forceUpdate() to force a re-render, https://facebook.github.io/react/docs/component-api.html#forceupdate.
Or more likely you should use this.setState(), https://facebook.github.io/react/docs/component-api.html#setstate.
I currently struggle with when/where to use state as apparently it's not advised. Search for react avoid state for more information.

Categories

Resources