Why can't I access and setState here? - reactjs

I have this handle change function. I cannot figure out why in the timeout section, I cannot access this.state? It works if I do it outside of that?
The part where i'm trying to setState employment_level gives me an 'undefined' error.
The console log console.log(${targetName}: ${targetValue}); works perfecly... but the two that reference this.state.empoloyee and this.state.employment_level do not.
handleChange = e => {
const targetName = e.target.name;
const targetValue = e.target.value;
this.setState({
[targetName]: targetValue,
});
if (this.state.editingTimeout) {
clearTimeout(this.state.editingTimeout);
}
this.setState({
editing: false,
editingTimeout: setTimeout(function () {
console.log(`${targetName}: ${targetValue}`);
this.setState({
employment_level: targetValue,
});
console.log(this.state.employee);
console.log(this.state.employment_level);
}, 300),
});
}

Maybe it works if you use an arrow functions in:
editingTimeout: setTimeout(() =>

Related

Why are state values ​returning undefined? with reactjs

const [value, setValue]=useState();
useEffect(() => {
authService.getAddr().then((response) => {
setndata(response.data);
},
(error) => {
console.log(error);
}
);
ndata.filter((obj) => obj._id === dataidM).map((data) => setValue(data.AddressTitle));
}, [dataidM, ndata]);
const [formData, setFormData] = useState({
billingAddr: false,
shippingAddr: false,
AddressTitle:`Hello, ${value} !` **// value is undefined**
});
return (
<div> ......
<div className='bg-info'>
{dataidM} --- {ndata.filter((obj) => obj._id === dataidM).map((data) => { return
data.AddressTitle })} -- --{value}
</div> **//I can see the values ​​as I want here when I check**
</div>
)
Why is it returning undefined in the other place, how can I show this value there? By default it should appear.
To connect the variables you need to add an effect like so:
useEffect(() => {
setFormData({
billingAddr: false,
shippingAddr: false,
AddressTitle:`Hello, ${value} !`
});
}, [value]);
This way every time value changes formData will change with it.
*a good note is that it is not recommended to use variables like so and just use Hello, ${value} ! in the rendering instead of a new variable.
More details as to why it was undefined:
const [formData, setFormData] = useState({
billingAddr: false,
shippingAddr: false,
AddressTitle:`Hello, ${value} !` **// value is undefined**
});
Here you set the default of the value and this default uses the default value, which is undefined as you set it here:
const [value, setValue]=useState(/*Here empty means undefined*/);
setState actions are asynchronous and are batched for performance gains. This is explained in the documentation of setState.
setState() does not immediately mutate this.state but creates a
pending state transition. Accessing this.state after calling this
method can potentially return the existing value. There is no
guarantee of synchronous operation of calls to setState and calls may
be batched for performance gains.
Below code might not execute like you expected.
useEffect(() => {
authService.getAddr().then(
(response) => {
setndata(response.data);
},
(error) => {
console.log(error);
}
);
ndata
.filter((obj) => obj._id === dataidM)
.map((data) => setValue(data.AddressTitle));
}, [dataidM, ndata]);
You are making an asynchronous request and updating the value without waiting for the response itself. I just modified your code like below. Test and let me know if you find any issues.
useEffect(() => {
const api = async () => {
try {
const response = await authService.getAddr();
setndata(response?.data);
response.data
?.filter((obj) => obj._id === dataidM)
.map((data) => setValue(data.AddressTitle));
} catch (error) {
console.log(error);
}
};
api();
}, [dataidM, ndata]);
As #Mihail Vratchanski suggested, it's always good to initialize state values with a default value.

React.JS TypeError: Cannot read property 'number' of undefined - (inside setState)

Hello everyone,
In my ReactJS website I get this error - `TypeError: Cannot read property 'number' of undefined`
`HTMLInputElement.anonymous ` why ?
I did console.log(this.state.number) and number has a value in it.
class App extends Component {
constructor(props) {
super(props);
this.state = {
mobileNum: '',
number: '',
};
}
somefunction=()=>{ // Is called with onKeyDown - I checked it does.
this.setState({ number: document.getElementById('mySubmit').value });
enterPressed = () => {
const submit = document.getElementById('mySubmit');
submit.addEventListener('keyup', function (event) {
if (event.key === 'Enter') {
this.setState({ mobileNum: this.state.number }); // Here is the error line !
}
});
};
If I use setState with if condition in another function it will do error - setState is not a function
this.setState({ mobileNum: this.state.number }) is working also in a different fuction I made, but in enterPressed() isn't.
Thanks for the helpers :)
It should be a fat arrow function
enterPressed = () => {
const submit = document.getElementById('mySubmit');
submit.addEventListener('keyup', (event) => {
if (event.key === 'Enter') {
this.setState({
mobileNum: this.state.number
});
}
});
};
You never call someFunction() which is supposed to assign a number value to this.state.number. When you try to assign this.state.number to mobileNum, the value is still undefined.
Instead of using HTML selectors in this function, you can add two-way binding:
enterPressed = (e) => {
e.preventDefault();
let password = e.target.value();
this.setState({ ...this.state, mobileNum: password});
};

simulate change not working with trim() enzyme

I was using this test when I had a bug, so I used the trim function for resolve it, and the these test fail, tried in different ways but didn't found the solution
const generalWrapper = shallow(<AddVehiclesTable {...generalProps} />)
const generalInstance = generalWrapper.instance()
describe('onSearchChange', () => {
test('should change the "search" state', () => {
const theFilterValue = 'a new filter value'
generalWrapper.find('.filter-input').simulate('change', { target: { value: theFilterValue } })
const expectedState = Object.assign({}, generalInstance.state)
expectedState.searchValue = { 'target': { 'value': theFilterValue } }
expect(generalInstance.state).toEqual(expectedState)
expect(generalInstance.state.userInteractedWithComponent).toBe(true)
})
})
onSearchChange (searchValue) {
const value = searchValue.trim()
this.setState({ searchValue: value, userInteractedWithComponent: true })
}
Error message
TypeError: searchValue.trim is not a function
Any suggestions
Your function gets the Object as a parameter.
Expose field that you needed
I don't see the whole picture, but can guess that you need something like
onSearchChange ({ target: { value: incomeValue } }) {
const value = incomeValue.trim()
this.setState({ searchValue: value, userInteractedWithComponent: true })
}

Simple setState on object using hooks

const [state, setState] = useState({ city: '', country: '' });
const handleCityChange = event => {
setState(prevState => {
console.log(prevState);
return { ...prevState, city: event.target.value };
});
};
//...
<input
type="text"
placeholder="city"
value={state.city}
onChange={handleCityChange}
/>
I'm trying to destructuring prevState, which is an object, and update only the city property. On first keystroke, it's working fine without error, but as soon as I'm typing second letter, i will hit error
Uncaught TypeError: Cannot read property 'value' of null
May I know which part is the null coming from? And from chrome console I see below warning not sure if it's related
Warning: This synthetic event is reused for performance reasons. If you're seeing this, you're accessing the property target on a released/nullified synthetic event. This is set to null. If you must keep the original synthetic event around, use event.persist(). See https:...//react-event-pooling for more information.
UPDATES:
If we're not using setState functionally, then it's working fine?
const handleCityChange = event => {
setState({ ...state, city: event.target.value });
};
An event has to be handled synchronously in React. You can extract the value from the target before you call setState:
const handleCityChange = event => {
const { value } = event.target;
setState(prevState => {
return { ...prevState, city: value };
});
};
Another way of going about it is to persist the event, and it can be used asynchronously.
const handleCityChange = event => {
event.persist();
setState(prevState => {
return { ...prevState, city: event.target.value };
});
};

setState is not defined

I have a print function, it first sets the state of isPrinting to true and open a pring dialog. Once the dialog is being closed it sets the state of isPrinting to false and at this point I'm getting the error (second setState):
Uncaught ReferenceError: setState is not defined
I binded function to current context with the arrow function.
handlePrint = () => {
this.setState({ isPrinting: true }, () => { //setState is working working properly
window.print();
if (window.matchMedia) {
var mediaQueryList = window.matchMedia('print');
mediaQueryList.addListener = (mql) => {
if (!mql.matches) {
this.setState({ isPrinting: false }); //Error
}
}
}
});
};
I am not sure what you are trying to achieve here but the window.print() freezes the app. There is no code being run unless someone clicks the printing screen away. I works just like window.alert("..."). You can try that by printing a thimestamp right after the win.print. So besides that there is a problem with the this context that cannot be reached the whole function is useless. Because you could just do:
handlePrint = () => {
this.setState({ isPrinting: true }, () => {
window.print() //freezes until someone clicks it away.
this.setState({ isPrinting: false }) //Error
})
}
Regards
Try this.
handlePrint = () => {
let _this = this;
this.setState({ isPrinting: true }, () => {
window.print();
if (window.matchMedia) {
var mediaQueryList = window.matchMedia('print');
mediaQueryList.addListener = (mql) => {
if (!mql.matches) {
_this.setState({ isPrinting: false });
}
}
}
});
};
This should help
handlePrint = () => {
this.setState({ isPrinting: true }, () => { //setState is working working properly
window.print();
if (window.matchMedia) {
var mediaQueryList = window.matchMedia('print');
mediaQueryList.addListener = (mql) => {
if (!mql.matches) {
return { isPrinting: false };
}
}
}
});
};
setState method should return a new state rather than try to execute anything.
At the second time, instead of setState, just return the new state like:
return {
isPrinting: false,
};
How did you use the function 'mediaQueryList.addListener'?You can console the two 'this' and see if they are same.

Resources