reading image from src/assets folder at runtime using props in React - reactjs

I want to display image randomly in React.
Images are placed inside src/assets folder.
I have to display them using props.
Row.js:
import React from 'react'
import {View, Text } from 'react-native';
const Row = (props) => (
<View style={{flex:1, flexDirection: 'row'}}>
<img src={require(props.value)}> //Error: Cannot find module '../assets/icondelivery.PNG'
</img>
<Text>{props.value}</Text>
</View>
)
export default Row
props.value contains : ../assets/icondelivery.PNG
Hierarchy is : src/assets/icondelivery.PNG
Note: If I pass <img src={require('../assets/icondelivery.PNG')}> , it works.

Put assets folder in public folder. Change path from ../assets/icondelivery.PNG to ./assets/icondelivery.PNG
Use this code:
import React from 'react'
import {View, Text } from 'react-native';
const Row = (props) => (
<View style={{flex:1, flexDirection: 'row'}}>
<img src={process.env.PUBLIC_URL + props.value}/>
<Text>{props.value }</Text>
</View>
)
export default Row

For dynamic image sources that are known then you can use require() in your definitions instead of within the img src itself.
For example
<Row value={require('../assets/icondelivery.PNG')} />
Then in the component:
<img src={props.value}>
If you have a structure containing the images like an array you could put require() there:
const images = [
{ name: 'delivery', src: requiure('../assets/icondelivery.PNG')}
...
...
]

Related

Why nativewind styles doesn't work if the styling is done at component level?

React-native styling using Nativewind works fine if the styling is done at App.Js. Like here:
<NavigationContainer>
<View>
<Text className = "text-red-500">Hello</Text>
</View>
</NavigationContainer>
But if the styling is done at component level, then it doesn't work anymore.
return (
<NavigationContainer>
<HomeScreen/>
</NavigationContainer>
);
HomeScreen Component:
import { View, Text } from 'react-native'
import React from 'react'
const HomeScreen = () => {
return (
<View>
<Text className = "text-red-500">Hello</Text>
</View>
)
}
export default HomeScreen
You'll need to tell nativewind the locations of where your components reside by adding this to your tailwind.config.ts
content: ["./App.{js,jsx,ts,tsx}", "./<custom directory such as src>/**/*.{js,jsx,ts,tsx}"],
reference: https://www.nativewind.dev/quick-starts/react-native-cli
If you setup folder in tailwind.config.js and still not work then delete nodemodule then install it again and it will work.
This works for me:
content: ["./App.{js,jsx,ts,tsx}", "./<custom directory such as src>/**/*.{js,jsx,ts,tsx}"]

tailwind-rn tailwind function returns empty object

I was trying to set up tailwind-rn in my project, but it seems impossible. The documentation says you should use yarn add tailwind-rn to install, then npx setup-tailwind-rn to set it up. This is a code example on the github page:
import React from 'react';
import {SafeAreaView, View, Text} from 'react-native';
import {useTailwind} from 'tailwind-rn';
const Hello = () => {
const tailwind = useTailwind();
return (
<SafeAreaView style={tailwind('h-full')}>
<View style={tailwind('pt-12 items-center')}>
<View style={tailwind('bg-blue-200 px-3 py-1 rounded-full')}>
<Text style={tailwind('text-blue-800 font-semibold')}>
Hello Tailwind
</Text>
</View>
</View>
</SafeAreaView>
);
};
export default Hello;
My code looks like this:
import { StyleSheet, Text, View } from 'react-native';
import {useTailwind} from 'tailwind-rn';
export default function App() {
const tailwind = useTailwind();
return (
<View style={tailwind('text-white')}>
<Text>Open up App.js to start working on your app!</Text>
</View>
);
}
The code does not throw any error, but simply produces nothing. I also checked the value of tailwind('text-white'), which seems to be just an empty object. Why does that not work?
Add this to your dependencies (package.json)
"tailwind-react-native-classnames": "^1.5.1",
and Import it in your project page like this,
import tw from "tailwind-react-native-classnames";
Finally use the tailwind styles like this,
style={tw`flex-1`}
<View style={[tw`bg-gray-200`, { height: 0.6 }]} />
And finally your code will work.

React -- Mapping specific images to specific cards

Trying to map specific images to specific card components as backgrounds. Problem - When I pass data.bgUrl into style={{ backgroundImage:`url(${data.bgUrl})`}} the result is surrounded by quotes ("img1") instead of just path name (img1). As a result, images won't load. Any insights?
import AthleteData from "../athletes.json";
import img1 from "../assets/img1.png";
import img2 from "../assets/img2.png";
import img3 from "../assets/img3.png";
import img4 from "../assets/img4.png";
....etc
import Card from "./Card";
import "./cards.scss";
export default function Cards() {
return (
<div className="cards-container">
<div className="cards">
{AthleteData.map((data, key) => {
return (
<div
key={key}
style={{
backgroundImage: `url(${data.bgUrl})`,
}}
>
<Card
key={key}
name={data.name}
date={data.date}
link={data.link}
/>
</div>
);
})}
</div>
<h3>Load More Cards</h3>
</div>
);
}
If you used backgroundImage in style, you don't need to import images. Please check your data.bgUrl is the correct path for each image.
also, set the image size through width and height, or backgroundSize in the style. You may need to set backgroundRepeat in the style as well.
I'm assuming that the 'AthleteData' you are importing is an object where one of the properties is called 'bgUrl' and that the value of that property is set to be a string such as 'img1'. The problem with that, if it is the case, is that the line where you are attempting to call that property (of bgURL) is that it still only represents a string, even if you have an imported variable that is called 'img1' as well. In your Athletes.json file you would want to have a dynamic reference to the image location. The problem with this is that .json files don't support import statements.
What I would recommend doing is to make a simple Javascript file where you import all your images as you did above and set them into a single object below them. Set the property 'bgUrl' to the dynamic references that those import statements create, and then you should be good. I will demonstrate below:
//This would be the new athletes.js file. Not a .json file
import img1 from "../assets/img1.png";
import img2 from "../assets/img2.png";
import img3 from "../assets/img3.png";
import img4 from "../assets/img4.png";
....etc
const AthleteData =
[
{name: 'Athlete1', bgUrl:img1, ...},
{name: 'Athlete2', bgUrl:img2, ...},
{name: 'Athlete3', bgUrl:img3, ...}
]
export default AthleteData
Then when you import this and use it in your jsx it would look like so:
import AthleteData from "../athletes.js";
// No longer importing those image refrences here
import Card from "./Card";
import "./cards.scss";
export default function Cards() {
return (
<div className="cards-container">
<div className="cards">
{AthleteData.map((data, key) => {
return (
<div
key={key}
style={{
backgroundImage: `url(${data.bgUrl})`,
}}
>
<Card
key={key}
name={data.name}
date={data.date}
link={data.link}
/>
</div>
);
})}
</div>
<h3>Load More Cards</h3>
</div>
);
}
Everything should roughly be the same in your jsx but you wouldn't need the import statements.

Create a PDF document after click a button in React

I want to generate a PDF document that is generated after user click "Create PDF document" for my current React page. The document I want to generate will have the following:
Some, but not all component in the current page
Selectable
Only download the document when clicking and nowhere else
I have spent 3 hours researching on this trivial task, but somehow all library I have looking up for only allow their pre-defined component, or not selectable, or both. I know that this task is very trivial, but how exactly I could do that?
The best way to do this is, having a separate component that only contains what data need to be downloaded. And you can pass all necessary data using props.
I recommend using this library React-PDF.
App.js
import { PDFDownloadLink } from '#react-pdf/renderer';
import Document from './Document.js'
export default function App() {
const data = {/* Pass your data here */}
return (
<div className="App">
<PDFDownloadLink document={<MyDocument data={data}/>} fileName="somename.pdf">
{({ blob, url, loading, error }) =>
loading ? 'Loading document...' : 'Download now!'
}
</PDFDownloadLink>
</div>
);
}
Document.js
import React from 'react';
import { Document, Page, Text, View, StyleSheet } from '#react-pdf/renderer';
// Create styles
const styles = StyleSheet.create({
page: {
flexDirection: 'row',
backgroundColor: '#E4E4E4'
},
section: {
margin: 10,
padding: 10,
flexGrow: 1
}
});
// Create Document Component
const MyDocument = ({ data }) => ( //
<Document>
<Page size="A4" style={styles.page}>
<View style={styles.section}>
<Text>{data.something}</Text>
</View>
<View style={styles.section}>
<Text>{data.something}</Text>
</View>
</Page>
</Document>
);
In the main component, you will have a Download now! button. Your PDF will only contain data that you pass through props

How to use a SVG React component as background?

I have SVG files written in Function Components.
import React from "react";
const MySVGBackground= (props) => {
return (
<svg> some svg here</svg>
);
};
export default MySVGBackground;
I need to render this as a background:
<div style={{ backgroundImage: `url(${MySVGBackground})` }}> </div>
but it's not working.
I can't purely import the SVG directly, because it gives me an error of Unexpected Token. So I have to wrap the SVG into the FC and export it.
Here is the sample code:
https://codesandbox.io/s/react-background-issue-9wt4x?file=/src/App.js
Try this:
https://codesandbox.io/s/react-background-issue-ut933
import React from "react";
import "./styles.css";
import BackgroundSVG from "./backgroundSVG";
// import this to render static markup
import { renderToStaticMarkup } from 'react-dom/server';
export default function App() {
// convert component to string useable in data-uri
const svgString = encodeURIComponent(renderToStaticMarkup(<BackgroundSVG />));
return (
<div className="App">
<h2
style={{
backgroundImage: `url("data:image/svg+xml,${svgString}")`
}}
>
Svg background
</h2>
</div>
);
}
The data: image/svg+xml;utf8 part tells the browser that raw image data is following.
More information can be found here:
https://css-tricks.com/lodge/svg/09-svg-data-uris/
https://gist.github.com/iansinnott/2e8fe9d9e4c6c7c55793d38f81c999a3

Resources