React - Cannot read property 'target' of undefined - javascript

I'm invoking a function like below and understand this is why im getting this error. Is there a way to not invoke the function but still pass the event property?
onMouseOver={(event) => { this.moveBall(event) }}
The reason for wanting to do this is so I can do a check in the function like so:
const element = event.target ? event.target : event;
As I want to re-use this function to pass an element through on load:
// Below line is in a constructor.
this.navItem = document.querySelector('.navigation__item');
// Being called after my render
this.moveBall(this.props.navItem);
Feels like this should be doable..
I've managed to fix this with the below code but I believe that there must be a better way to achieve this:
window.addEventListener('load', () => {
const activeState = document.querySelector('.navigation__item .active')
this.moveBall(activeState)
});
** Update **
Full component code
https://jsfiddle.net/fvn1pu5r/

According to your last update all you need is just move first call to this.moveBall to react lifecycle hook componentDidMount. This ensures that DOM will have .navigation_item nodes in it. So, remove lines
window.addEventListener('load', () => {
const activeState = document.querySelector('.navigation__item .active')
this.moveBall(activeState)
});
from render method and add componentDidMount method to your class, like this:
componentDidMount() {
const activeState = document.querySelector('.navigation__item .active');
this.moveBall(activeState);
}
This should work.

Your moveBall function is being called with undefined as the argument at some stage. The event.target ? check then crashes with the error you gave.
The onMouseOver is likely always fine, as React supplies that.
Instead, I imagine it's the manual call you gave at the end. Is there a time when your this.props.navItem doesn't have a value?
Worth logging out that property right before calling the function to be sure it's always as you expect.

Related

component is getting loaded for fraction of second in React

I have one query call which returns me the data and also I am using await as well.
const {data, isLoading } = useQuery('getData', queryFunc);
here ,
I am trying to use it here
<div>
{ data?.addition?.isEnabled && <Notification> }
</div>
Here, for fraction of second the Notification component is getting rendered., and after 1-2 second once response comes then the component is rendered.
Is there any specific reason for this? also How do I fix this ?
I fixed this like { data && data?.addition?.isEnabled && <Notification> }
can any one help me with this?
In React undefined and false values are not rendered. Since the data you're getting is from an async function the notifications component will be rendered briefly until initialized and then removed. You can maybe use a useCallback hook to fix this behavior but without seeing more of the code I'm not sure on what to do.
Usage of useCallback is like so:
const foo = useCallback(() => { //you can pass parameters here when calling like this foo(arg1,arg2)
//do something expensive in resources...
//this will re-render when done.
return bar;
},[//dependencies go here]);
//use with useEffect hook if you want this to render on load like so:
useEffect(() => {
foo();
},[foo]);

React fullCalendar, reaching this.props in eventReceive function

I want to set one of my parent's attributes with my event's start time, but I cant reach this.props from inside the function(info) method. How could I reach tha method I want to use?
eventReceive={function (info) {
this.props.onChangeStartDate(info.start);
}}
onChangeStartDate is one of my parent's function which sets the starting date of an appointment in the parent component and I want to give the event's data which I just added in the calendar as a parameter to that function.
I got the following error:
Cannot read property 'onChangeAppointment' of undefined
Thanks for your help.
The following will solve your error.
eventReceive={(info) => {
this.props.onChangeStartDate(info.start);
}}
Where
() => {} is an arrow function commonly used. See documentation.
The reason the error is occuring is because you losing the context of this inside the scope of the function.

How to call a component's onClick prop for testing purposes?

I'm using Jest and Enzyme to test some React components (written using TypeScript). My old method was to use Enzyme's .simulate() function to simulate a click, but this is being deprecated in favor of using instance prop functions (i.e. just using the component's onClick() prop). However, I'm not sure how exactly to call the onClick() function directly. Below is my code:
// Get the onClick function
const buttonOnClick = wrapper.find('#diffpicker-button').first().props().onClick;
// buttonOnClick could be a function or undefined, make sure its a function
if (!buttonOnClick) return;
// Assignment needed here, but to what?
let event: React.MouseEvent<Element, MouseEvent>;
// How to call it?
buttonOnClick(event);
I need to assign my event variable to pass to buttonOnClick(), but what should I assign it to? What does an onClick event actually look like? Or, am I going about this all wrong?
You can call onClick directly using a mock event definition like below:
// arrange
const event = {
preventDefault: jest.fn(),
};
// act
wrapper.find("MobileLink").last().props().onClick(event);
// assert
.
.
.

How do I obtain updated props mid-async-function?

This is for an open-source project called react-share, and their ShareButton component has a prop called beforeOnClick that you can pass to it. I'm using beforeOnClick to upload an image to our CDN so that we don't needlessly upload images that don't get shared, which causes the url prop passed to the button to update.
My current problem is, after beforeOnClick runs, the share button currently doesn't handle the updated url prop.
Basically, I have an async function that looks something like this:
const handleClick = async () => {
const { url, disabled, beforeOnClick } = this.props;
// beforeOnClick can cause this.props to change. beforeOnClick can also perform async operations, like making a fetch call
if (beforeOnClick) {
await beforeOnClick();
// call setTimeout to delay the next handleClick call in order to ensure this.props
// properly reflects changes from the parent component
setTimeout(handleClick);
return;
}
// Do stuff with url & disabled
};
I dumbed it down for the sake of keeping the question simple, but if you'd like to view the code I currently have, check out my fork. compare to the original.
Is setTimeout a reliable way to achieve this effect? Or, should I do something like this instead:
this.setState({ __rerender_component: true }, handleClick);
I'm not a huge fan of that solution, as I'd have to manage resetting that flag after the callback is run. Any thoughts are appreciated!
EDIT: Using setTimeout seems to work, but I'm not sure if it's reliable. If it fails 1/100 times, that sucks.
It might be easiest and feels more "reacty" to use setState to have a local copy of the props and let the beforeOnClick function use setState?
eg (beware, I have been using hooks only on my latest projects, so might be off)
const handleClick = async () => {
this.state = this.props; // can all props be changed?
if (beforeOnClick) {
await beforeOnClick(this.setState);
// Do stuff with this.state.url & this.state.disabled };
and beforeOnClick can use setState to change the url and others.
instead of giving full control to setState, you might want to have a different approach:
let newState= await beforeOnClick();
if (newState && newState.url && !newState.url.startsWith("http"))
throw 'url must start with http';
// that might be a wrong assumption, take it as an example
// whatever else you want to check, like disable is a boolean...
this.setState({...state, ...newState});

Cant change variable with callback function but console logging works

I am trying to change a variable in react with a callback function but cannot seem to do so. Here is my react component:
const MyComponent = () => {
let scenePinned;
const sceneCallback = event => {
if (event && event.state === 'DURING') {
console.log('Pinned');
scenePinned = true;
} else {
console.log('Not Pinned');
scenePinned = false;
}
};
console.log(scenePinned);
return (
<div>
<div style={scenePinned ? 'pinned' : 'not pinned'}/>
{(progress, event) => (
//Stuff Happens Here
), sceneCallback(event) )}
</div>
);
}
I am using react-scrollmagic and am trying to get the scenePinned variable to change from false to true and back to false again when scene is pinned to top. The console logging of Pinned and Not Pinned is happening correctly but I cannot seem to change the scenePinned variable. I am sure this is something very basic that I am not getting but I cannot understand why this is happening. Any help would be appreciated.
Note: I have tried using state to store the value but the callback is fired on scroll so the maximum depth is exceeded when trying to use state to store the scrolling status.
You need to use state for this. Otherwise the variable is reinitialized every time the component is rendered, and the value is lost.
console.log(scenePinned);
will run for the first time when the page loads
with react we use state the handle dynamic values.
or use rxjs
or create your own object and set listeners on it. with some custom event
so ex. with state
state={scenePinned:null}
then inside render method console.log(this.state.scenePinned)
A possible solution is to define a state variable in a parent component that will pass it to <MyComponent> as a prop.
Them move the sceneCallback function to the parent component and pass it as a prop to <MyComponent>
An explanation on how to define such a callback exists in many places. Here is one: (mine... ;) https://stackoverflow.com/a/55555578/5532513

Categories