React Native throw null is not an object - javascript

I have a problem understanding why this code isnt working.
If i use it like this:
const [theInfo , setTheInfo] = useState(null);
return (
theInfo ?(
...):(
...)
Its working without any problems. But as soon as i add a View or anything above or after theInfo... like this:
const [theInfo , setTheInfo] = useState(null);
return (
<View>
<View>
<Text>Hi</Text>
</View>
theInfo ?(
...):(
...)
</View>
Then I get this error: TypeError: null is not an object (evaluating 'theInfo.map')
I dont understand why this is happening. I want to set a searchbar on top, and after this the theInfo?(... part

theInfo is a variable, you can't use it jsx in such a way, inclose it in curly braces :
const [theInfo , setTheInfo] = useState(null);
return (
<View>
<View>
<Text>Hi</Text>
</View>
{
theInfo ?(
...):(
...)
}
</View>

Related

"Each child in a list should have unique key" error persists after adding key prop

New to react native, and I know that each list element needs a unique key prop, but I thought I provided one here in the text element. Please guide me in the right direction.
const BadFood = ({ ingredients }) => {
return (
<View>
<Text>Bad Ingredients</Text>
{ingredients.map((ing) => (
<View>
<Text key="{ing}">{ing}</Text>
</View>
))}
</View>
);
};
This is the array I'd like to destructure in firebase BadIngr = ["Peanuts", "Dairy"]
As #jnpdx mentioned change your code as follows:
const BadFood = ({ ingredients }) => {
return (
<View>
<Text>Bad Ingredients</Text>
{ingredients.map((ing) => (
<View key={ing}>
<Text>{ing}</Text>
</View>
))}
</View>
);
};

How to do a this with a component in react native?

I am working with react native and expo.cli and would like to know how I can manage to add a handle to a TouchableOpacity, I have the following component:
function MainModal (){
return(
<>
<View style={{flexDirection: 'row'}}>
<TouchableOpacity
onPress={this.TouchableOpacity}
>
<Text>Volver</Text>
</TouchableOpacity>
</View>
</>
What I want to do is make a reference to this specific TouchableOpacity when it is selected, but when I use a "this" nested in the component I get the following error: Undefined is not an object (Evaluating 'this.TouchableOpacity') I know maybe This question is a bit of a novice and has more to do with how 'this' works in javascript than with React Native itself, however I can't find a way to make a reference to the selected object so that it executes something when selected. How could I do it?
You can use React.useRef() hook to create a reference to that element so you can access then to it. The idea you have of this is not the actual this. This might refer to the global object (in not strict) and might be undefined in strict mode. If you want to use this in a component I recommend you to create a class component instead of a function one. See this in MDN to learn more of it.
Anyway, the use of ref in a functional component would be this:
function MainModal (){
const touchableReference = React.useRef()
const handleTouchableClick = () => {
console.log(touchableReference.current)
//
// Outputs HTMLDivElement...
//
}
return(
<>
<View style={{flexDirection: 'row'}}>
<TouchableOpacity
ref={touchableReference}
onPress={() => handleTouchableClick()}
>
<Text>Volver</Text>
</TouchableOpacity>
</View>
</>
)
}
One standard way of passing event handler in functional component is as follows
function MainModal (props){
const onPress1 = useCallback(()=>console.log); // created inside the componet
const {onPress2} = props; // passed from props
const {onPress3} = useSomeHook(); // from context/hook
return(
<>
<View style={{flexDirection: 'row'}}>
<TouchableOpacity
onPress={onPress1}
>
<Text>Volver</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={onPress2}
>
<Text>Volver</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={onPress3}
>
<Text>Volver</Text>
</TouchableOpacity>
</View>
</>
);
}
The behaviour of this works the same in react and react-native. React functional component is executed during the render phase and you are not suppose to work with this here, given that you do not understand when and where it is called.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

Top navigation items in header constantly flickers when typing

The image in the header constantly flickers when I type. May I ask how do I stop this flickering at the top right hand corner or accessoryRight? I am using this TopNavigation component from UI Kitten UI library. I don't think this is normal, it shouldn't happen at all. I must be doing something wrongly.
https://youtu.be/fQppQn-RzeE (How do I embed this? Editor, thank you in advance!)
The flickering happens in the title and the right side of the Navigation Header.
I made a separate component for the TopNavigation and then call it in respective screens.
Things I have tried:
Since the outcome of the Header relies on navigation props, I tried using useState and useEffect (with navProps as the dependency) to save the prop instead of reading directly from props, but to no avail
Directly adding the jsx into the TopNavigation's accessoryLeft/Right and title options
Any input is welcome, appreciate it!
TopNavigation:
const NavHeader = ({ navProps }) => {
const navigateBack = () => {
navProps.navigation.goBack();
};
const [type, setType] = React.useState('');
React.useEffect(() => {
setType(navProps.type);
}, [navProps]);
const BackIcon = props => <Icon {...props} name='arrow-back' />;
const BackAction = () => (
<TopNavigationAction icon={BackIcon} onPress={navigateBack} />
);
const renderBrand = () => (
<View style={styles.titleContainer}>
<Image source={require('../../assets/images/brand.png')} />
</View>
);
const renderLogo = () => (
<Image source={require('../../assets/images/logo.png')} />
);
return (
<TopNavigation
style={styles.topNav}
accessoryLeft={navProps.backNav && BackAction}
accessoryRight={
type === 'register' || type === 'profile' ? renderLogo : null
}
title={type === 'landing' || type === 'auth' ? renderBrand : null}
alignment='center'
/>
);
};
Import example:
<KeyboardAvoidingView
style={styles.kbContainer}
behavior={Platform.OS === 'ios' ? 'padding' : null}
>
<SafeAreaView style={styles.parentContainer}>
<NavHeader navProps={navProps} /> // Imported custom Header component here
<ScrollView>
{other content}
</ScrollView>
</SafeAreaView>
</KeyboardAvoidingView>
Perhaps requiring the images just one time and not on every render may help.
Try adding this at the top of the file (not inside a component function)
const brandImage = require('../../assets/images/brand.png');
const logoImage = require('../../assets/images/logo.png');
And then in your props instead of an inline require use the variables:
const renderBrand = () => (
<View style={styles.titleContainer}>
<Image source={brandImage} />
</View>
);
const renderLogo = () => (
<Image source={logoImage} />
);
Edit:
Since this didn't work, perhaps utilizing useMemo to memoize the components that show the images would work?
Something like
const renderBrand = useMemo(() => (
<View style={styles.titleContainer}>
<Image source={brandImage} />
</View>
),[]);
const renderLogo = useMemo(() => (
<Image source={logoImage} />
),[]);

React Native Prevent Undefined Objects

I am grabbing data from an API to display an image based on the API value. The following code works perfect IF there is an image in the object. If an API item does not have an image the app throws an "Undefined is not an object" error.
<View>
<Image source={{uri:props.enclosures[0].url}} style={styles.mainPhoto} />
</View>
I have tried the following code to check if the value exists first, but it still throws exact same error if an API item does not have image.
<View>
{props.enclosures[0].url ?
<Image source={{uri:props.enclosures[0].url}} style={styles.mainPhoto} />
:
<Text>No Image</Text>
}
</View>
If you are going to access multiple properties of a nested object, you should check everything, like so
<View> // Checking everthing so it never throws an error
{props.enclosures && props.enclosures[0] && props.enclosures[0].url ?
<Image source={{uri:props.enclosures[0].url}} style={styles.mainPhoto} />
:
<Text>No Image</Text>
}
</View>
To prevent undefined error you can also use path from Ramda library. It allows you to safely access any nested object/array.
const MyComponent = (props) => {
const apiImage = path(["enclosures", 0, "url"], props);
return {
<View>
{apiImage ?
<Image source={{uri:apiImage}} style={styles.mainPhoto} />
:
<Text>No Image</Text>
}
</View>
}
}

react-native-snap-carousel returns "Cannot read property 'concat' of undefined" when I use renderItme

I am learning React-Native and using react-native-snap-carousel in my project.
I want to show some images but I got error Cannot read property 'concat' of undefined.
Here is my code.
const HomePage = (props) => {
let imageList = ['../images/index-bg.png', '../images/down.png'];
const renderImage = ({ item, index }) => {
return (
<View>
<Image source={require(item)}></Image>
</View>
)
};
return (
<View>
<Carousel
loop={true}
autoplay={true}
data={imageList}
renderItem={renderImage}
sliderWidth={pxToDp(50)}
itemWidth={pxToDp(100)}
/>
</View>
)
}
If I change
<View>
<Image source={require(item)}></Image>
</View>
to
<View>
<Image source={'../images/index-bg.png'}></Image>
</View>
ยทยทยท
it works well
I expect it would work like [Usage](https://github.com/archriss/react-native-snap-carousel) but it doesn't work.
Did you try this?
let imageList = [require('../images/index-bg.png'), require('../images/down.png')];
and then
<View>
<Image source={item}></Image>
</View>
Required source for images in RN have to be defined before runtime
Let me know if it works!

Categories