In my expo typescript app, I have a function in a root component:
const getCardType = (type = ECardType.WOOD) => {
setCardType(type);
};
and pass it in my first child component:
<Slider data={slideData} autoPlay={false} getCardType={getCardType} />
Here is my first child component where I pass the function, and it types declaration:
readonly getCardType?: (type: ECardType) => void;
const Slider: React.FunctionComponent<ISliderProps> = ({
data,
autoPlay,
getCardType,
})
After that I pass it into a second child component:
<SliderCardItem cardItem={item} index={index} getCardType={getCardType} />
And in this SliderItem component, I use this function:
useEffect(() => {
getCardType(cardType);
}, [cardType]);
But Have a TS error: Cannot invoke an object which is possibly 'undefined' in children component
I set the cardType below in an onPress()
I have this error only in this component
An idea to fix this error?
CodePudding user response:
Remove the ?
in the type declaration, if it's required. If it's not required, you have to check if it exists first.
Another point, getCardType
is actually a dependency of that effect as well, but by looking at it it's safe, to ignore it (because it just wraps a setState) call.
I don't like ignoring stuff, though. So if I were you, I'd probably write it like this:
// useCallback makes getCardType referentially identical between renders
const getCardType = useCallback((type = ECardType.WOOD) => {
setCardType(type);
// safe to ignore setCardType in the dependencies because it's a dispatcher
},[]);
// ... and in the child:
useEffect(() => {
getCardType(cardType);
}, [ getCardType, cardType ]);
I'm honestly dying to know what that useEffect
is about in the child, because it smells a little fishy.
CodePudding user response:
getCardType
might be undefined, as stated in your type here:
getCardType?: (type: ECardType) => void;
Then you're trying to call it without checking if it exists:
useEffect(() => {
getCardType(cardType);
}, [cardType]);
So you'll need to perform that check:
useEffect(() => {
if (getCardType) getCardType(cardType);
}, [cardType]);
or with optional chaining:
useEffect(() => {
getCardType?.(cardType);
}, [cardType]);
If it will always be present then you can make it non optional in your type:
getCardType: (type: ECardType) => void;