Hi I am running into the error "Unknown named Module" when trying to dynamically update image using componentWillReceiveProps. Essentially I have a topics component which has a list of topics, when a topic is clicked it gives props to another component (thumbnails) and the images related to that topic are populated.
Here is some code for the thumbnails component:
import React, { Component } from 'react';
import { StyleSheet, Text, View, Image, Button } from 'react-native';
import Player from './player.js';
import styles from '../stylesheet.js';
let baseurl = '../assets/thumbnails/';
let extension = '.jpeg';
export default class Thumbnails extends Component {
constructor(props){
super(props);
this.state = {
current: [
require('../assets/thumbnails/narcolepsy-1.jpeg'),
require('../assets/thumbnails/narcolepsy-2.jpeg'),
require('../assets/thumbnails/narcolepsy-3.jpeg')
]
}
}
componentWillReceiveProps(nextProps) {
setTimeout(()=>{
let topic = nextProps.current.toLowerCase();
let current = [];
for(let i = 1; i <= 3;i++){
current.push(require(baseurl + topic + '-' + i + extension));
}
this.setState({current,})
},1000)
}
render() {
const thumbnails = this.state.current.map((path,i) => {
return(<Image
source={path}
style={styles["thumbnail"+(i+1)]}
key={"thumbnail"+i} />);
})
return(
<View style={{flexDirection:'row'}}>
{thumbnails}
</View>
)
}
}
I've found a similar question (React-native image - unknown named module '../img/2.jpeg') that says to use source={uri: 'file.extension'};
and to keep image assets in the folder android/app/src/main/res/drawable
However I do not have an android folder, as I am using CRNA and Expo.io. Here is my project structure, please tell me what to do in this context:
App.js app.json my-app-key.keystore stylesheet.js
App.test.js assets node_modules yarn.lock
README.md components package.json
Using dynamic require calls is not supported by the React Native packager. This is outlined in the docs: React Native - Images
In order for this to work, the image name in require has to be known statically.
// GOOD
<Image source={require('./my-icon.png')} />
// BAD
var icon = this.props.active ? 'my-icon-active' : 'my-icon-inactive';
<Image source={require('./' + icon + '.png')} />
// GOOD
var icon = this.props.active ? require('./my-icon-active.png') : require('./my-icon-inactive.png');
<Image source={icon} />
I would suggest creating a static data structure to hold your images, such as an object like:
const images = {
narcolepsy: [
require('../assets/thumbnails/narcolepsy-1.jpeg'),
require('../assets/thumbnails/narcolepsy-2.jpeg'),
require('../assets/thumbnails/narcolepsy-3.jpeg')
],
apnea: [
require('../assets/thumbnails/apnea-1.jpeg'),
require('../assets/thumbnails/apnea-2.jpeg'),
require('../assets/thumbnails/apnea-3.jpeg')
]
};
This way, the packager can load your references up when the bundle is created.
Related
i installed tailwind-rn for my react native project
i did the configuration and used this syntax provided in the console after installation
import {useTailwind} from 'tailwind-rn';
const MyComponent = () => {
const tailwind = useTailwind();
return <Text style={tailwind('text-blue-600')}>Hello world</Text>;
};
but for me i have a class component so i did this
render() {
const tailwind = useTailwind();
return (
<View style={tailwind("style classes...")}>
...
<View/>
);
}
and i got this error
Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
i searched how to use tailwind-rn for a class component and i didn't find something usefull.
the question is clear. I think it can be done with react native elements. But how? I am very new to react native.
I read the documentation in here. It has a code like this:
import { ThemeProvider, Button } from 'react-native-elements';
const theme = {
Button: {
raised: true,
},
};
// Your App
const App = () => {
return (
<ThemeProvider theme={theme}>
<Button title="My Button" />
<Button title="My 2nd Button" />
</ThemeProvider>
);
};
What if this part of the code:
const theme = {
Button: {
raised: true,
},
};
was coded in another file. How will I make the buttons raised?
You have 2 ways to aboard your problem.
First, if you want to use the same style for your react-native-elements components across certain files and they are all the children of the same parent file, you use this bit of code :
<ThemeProvider theme={theme}>
<Button title="My Button" />
<Button title="My 2nd Button"/> // ... plus any other component that contains your react native elements components
</ThemeProvider>
for this case if you want to put your config variable in another file , you can do it like this :
create a new file that contains your config variable let say for example a new file called config.js
// config.js file
export default {
Button:{
raised:true
}
// ... other RN-elements props
}
// or this
const theme = {
Button: {
raised: true,
},
}
export {theme}
then import it in your workspace like so :
// the file were you are using your themeProvider
import theme from "path_to_your_config.js_file"
// or respectively
import {theme} from "path_to_your_config.js_file"
// then use the variable theme as you like
the second way is that you create your own custom component and you style it however you want and you use it in your app.
Coming from reactjs i was expecting "alt" attribute on the image component that will show text in case the image could not be loaded.
I read the documentation here and the closest thing I found is the on error event.
Is there an attribute equal to alt in React Native image component? And what is the easiest way to replace your image with a default text if i don't have the alt attribute?
You can make such a component yourself, it requires a very minimal amount of code. Here's a basic example:
export default class AccessibleImage extends Component {
state = {
error : false
};
_onImageLoadError = (event) => {
console.warn(event.nativeEvent.error);
this.setState({ error : true });
}
render() {
const { source, alt, style } = this.props;
const { error } = this.state;
if (error) {
return (
<Text>{alt}</Text>
);
}
return (
<Image
accessible
accessibilityLabel={alt}
source={source}
style={style}
onError={this._onImageLoadError} />
);
}
}
This will show the provided alt if there was an error loading the image and also use that text as the accessibilityLabel for screen readers which is closer to web behaviour.
A better answer than the previous if using React Native 0.68+ is to include the alt attribute on an <Image> Component like so
<Image
style={styles.yourImageStyles}
source={{
uri: 'https://reactnative.dev/img/tiny_logo.png',
}}
alt={'Alternate text that will be read be screen readers'}
/>
Chatgpt said:
let displayImage;
try {
displayImage = <Image source={require('./secondImage.png')} />;
} catch (error) {
displayImage = <Text>Second Image not available</Text>;
}
and to use the image/text:
{displayImage}
I try to implement the hero animation like in the shoutem About extension. Basically, I add animationName to NavigationBar and the Image like in the extension. I also had to add ScrollDriver because it would error-ed otherwise. But it seems the NavigationBar does not pass the driver down to its child components, so I still got this error. Is it possible to implement the hero animation like what was demonstrated here? https://medium.com/shoutem/declare-peace-with-react-native-animations-e947332fa9b1
Thanks,
import { ScrollDriver } from '#shoutem/animation';
getNavBarProps() {
const driver = new ScrollDriver();
return {
hasHistory: true,
driver: driver,
title: 'Title',
navigateBack: () => this.props.navigation.dispatch(NavigationActions.back()),
styleName: 'fade clear',
animationName: 'solidify',
};
}
render () {
const driver = new ScrollDriver();
return (
<Screen styleName=" paper">
<View style={{height:68}}>
<NavigationBar {...this.getNavBarProps()} />
</View>
<ScrollView style={styles.container}>
<Image
styleName="large"
source={require('../Images/spa2.jpg') }
defaultSource={require('../Images/image-fallback.png')}
driver={driver}
animationName="hero"
/>
...
I'm the author of the article, from you question, I'm not sure are you trying to create an extension on shoutem or you just want to recreate animation in any other React Native app.
If you are creating an extension or CardStack from #shoutem/ui/navigation, you don't event need to care for ScrollDriver. It would be pushed throught the context to the ScrollView (imported from #shoutem/ui) and NavigationBar (imported from #shoutem/ui/navigation).
If you are creating your own React Native project to be able to do it like in article I suggest the following. At the root component of your app:
import ScrollView from '#shoutem/ui';
class App extends Component {
...
render() {
return (
<ScrollView.DriverProvider>
<App />
</ScrollView.DriverProvider>
);
}
}
Then you don't have to take care of initialization of ScrollDriver on each screen, if you use our components and a ScrollView it will push the driver where it needs to be. :) So your screen at the end would look like this:
import {
ScrollView,
NavigationBar,
Image
} from '#shoutem/ui';
class MyScreen extends Class {
render() {
return (
<Screen>
<NavigationBar animationName="solidify" />
<ScrollView>
<Image animationName="hero" />
</ScrollView>
</Screen>
);
}
}
The whole working example is here https://github.com/shoutem/ui/tree/develop/examples/RestaurantsApp/app
I'm trying to use shoutem/ui with exponent and I’m getting an error using the shoutem/ui textinput component, where I get the following error message fontFamily Rubik is not a system font and has not been loaded through Exponent.Font.loadAsync
However I loaded all the custom shoutem fonts that were listed in the blog post https://blog.getexponent.com/using-react-native-ui-toolkits-with-exponent-3993434caf66#.iyiwjpwgu
Using the Exponent.Font.loadAsync method.
fonts: [
FontAwesome.font,
{'space-mono': require('./assets/fonts/SpaceMono-Regular.ttf')},
{'Rubik-Black': require('./node_modules/#shoutem/ui/fonts/Rubik-Black.ttf')},
{'Rubik-BlackItalic': require('./node_modules/#shoutem/ui/fonts/Rubik-BlackItalic.ttf')},
{'Rubik-Bold': require('./node_modules/#shoutem/ui/fonts/Rubik-Bold.ttf')},
{'Rubik-BoldItalic': require('./node_modules/#shoutem/ui/fonts/Rubik-BoldItalic.ttf')},
{'Rubik-Italic': require('./node_modules/#shoutem/ui/fonts/Rubik-Italic.ttf')},
{'Rubik-Light': require('./node_modules/#shoutem/ui/fonts/Rubik-Light.ttf')},
{'Rubik-LightItalic': require('./node_modules/#shoutem/ui/fonts/Rubik-LightItalic.ttf')},
{'Rubik-Medium': require('./node_modules/#shoutem/ui/fonts/Rubik-Medium.ttf')},
{'Rubik-MediumItalic': require('./node_modules/#shoutem/ui/fonts/Rubik-MediumItalic.ttf')},
{'Rubik-Regular': require('./node_modules/#shoutem/ui/fonts/Rubik-Regular.ttf')},
{'rubicon-icon-font': require('./node_modules/#shoutem/ui/fonts/rubicon-icon-font.ttf')},
],
});
Looking through the code I couldn't find the obvious fix - had trouble even finding where the style was set to throw the error.
The code above seem to be missing one line. Try adding this line to the array list:
{'Rubik': require('./node_modules/#shoutem/ui/fonts/Rubik-Regular.ttf')}
Use this code from the link
import React, { Component } from 'react';
import { StatusBar } from 'react-native';
import { Font, AppLoading } from 'expo';
import { View, Examples } from '#shoutem/ui';
export default class App extends React.Component {
state = {
fontsAreLoaded: false,
};
async componentWillMount() {
await Font.loadAsync({
'Rubik': require('./node_modules/#shoutem/ui/fonts/Rubik-Regular.ttf'),
'Rubik-Black': require('./node_modules/#shoutem/ui/fonts/Rubik-Black.ttf'),
'Rubik-BlackItalic': require('./node_modules/#shoutem/ui/fonts/Rubik-BlackItalic.ttf'),
'Rubik-Bold': require('./node_modules/#shoutem/ui/fonts/Rubik-Bold.ttf'),
'Rubik-BoldItalic': require('./node_modules/#shoutem/ui/fonts/Rubik-BoldItalic.ttf'),
'Rubik-Italic': require('./node_modules/#shoutem/ui/fonts/Rubik-Italic.ttf'),
'Rubik-Light': require('./node_modules/#shoutem/ui/fonts/Rubik-Light.ttf'),
'Rubik-LightItalic': require('./node_modules/#shoutem/ui/fonts/Rubik-LightItalic.ttf'),
'Rubik-Medium': require('./node_modules/#shoutem/ui/fonts/Rubik-Medium.ttf'),
'Rubik-MediumItalic': require('./node_modules/#shoutem/ui/fonts/Rubik-MediumItalic.ttf'),
'Rubik-Regular': require('./node_modules/#shoutem/ui/fonts/Rubik-Regular.ttf'),
'rubicon-icon-font': require('./node_modules/#shoutem/ui/fonts/rubicon-icon-font.ttf'),
});
this.setState({ fontsAreLoaded: true });
}
render() {
if (!this.state.fontsAreLoaded) {
return <AppLoading />;
}
return (
<View styleName="flexible">
<Examples />
<StatusBar barStyle="default" hidden={false} />
</View>
);
}
}