problem while importing dynamic images to url in react - javascript

I am making a react project, where I want to import the set of images from a data.tsx file such that it should set inside the backgroundImage url of the element in which the 'data' is mapped into.
But, my images are not visible as the background image of the element, also I am not getting any kind of error message from the compiler instead. My code is as follows -
import start from "../assets/Board/hut.png";
import image2 from "../assets/Board/Man.png";
import image3 from "../assets/Board/Factory.png"
const Tiles = [
{
id: 1,
name: "start",
bgImage : `url(${start})`
},
{
id: 2,
name: "two",
bgImage : `url(${image2})`
},
{
id: 3,
name: "three",
bgImage : `url(${image3})`
}];
and now I am using it into my component as
import Tiles from "../../Data/tileData";
export default function Dashboard(){
return(
<>
<Grid container>
{Tiles.map((tile) => (
<Grid item xs={1} key={tile.id}>
<Paper elevation ={2} sx={{backgroundImage : `url(${tile.bgImage})` }}
</Grid>
))}
</Grid>
</>
)
}
I have tried almost every workAround this, but didn't get any concrete results. None of my method is mapping the background Image of the Paper element dynamically.
Methods I tried -
A.) By moving the images into the Public Folder and then setting it as the backgroundImage inside my component file's sx ={{}} attribute.
B.) By using my backgroundImage as
sx={{backgroundImage : tile.bgImage }}
C. ) By refactoring my orignal object array as -
const Tiles = [
{
id : 1,
name : "start",
bgImage : "/Board/hut.png" //after adding the Board folder inside Public folder.
}, {...}, {...}}];
and then passing the backgroundImage as
sx={{ backgroundImage : `url(${tile.bgImge})`}}
I have also refactored my data file as this -
const Tiles = [
{
id: 1,
name: "start",
bgImage : '/Board/hut.png'
},
{
id: 2,
name: "two",
bgImage : '/Board/Man.png'
},
{
id: 3,
name: "three",
bgImage : '/Board/Factory.png'
}];
//note - all the references to the images are now from inside the public folder instead.
but, it doesn't work instead
none of the above mentioned methods worked for me.
I want to set the 'backgroundImage' of the element mapping my 'object array' , is there any specific work around this?
suggestions are honoured

If you are using this import images in Object. That is going to treat as an object inside of Image tag (). try to import images on the Image tag and assign them.
import start from "../assets/Board/hut.png";
import image2 from "../assets/Board/Man.png";
import image3 from "../assets/Board/Factory.png"
const Tiles = [
{
id: 1,
name: "start",
bgImage : `url(${start})`
},
{
id: 2,
name: "two",
bgImage : `url(${image2})`
},
{
id: 3,
name: "three",
bgImage : `url(${image3})`
}];
Do this in array:
{
id: 1,
name: "one",
}
Better to define the name with id. and access from the same page. like this
import hut1 from "../assets/Board/hut.png";
import image2 from "../assets/Board/Man.png";
sx={{ backgroundImage : hut1}}
sx={{ backgroundImage : image2}}
For now, as per my experience, it's work.
One thing more, you can add image URL link in this that works too.
{
id: 1,
name: "start",
bgImage : 'https://picsum.photos/200'
}
But Definitely, I will share any other option if I got.

Related

React Native Image Binding

Trying to navigate some React Native image bindings which I am unsure how to proceed.
Right now, the following code works.
I have a data file of items:
MyData.js
import { Images } from '#configuration';
const myData = [
{
name: 'One',
img: Images.one
},
{
name: 'Two',
img: Images.two
},
{
name: 'Three',
img: Images.three
}
]
And the images.js file
export const Images = {
one: require('#assets/images/one.png'),
two: require('#assets/images/two.png'),
three: require('#assets/images/three.png')
}
And in my React screen, I am trying to render that as:
import {MyData} from '#data';
export default function MyScreen({navigation}) {
const [myData] = useState(MyData);
return (
<View>
<FlatList data={myData} keyExtractor={(item, index) => item.name}
renderItem={({item, index}) => (
<Card image={item.img}>
</Card>
)}
</>
</View>
)
}
The above displays the image accordingly.
Now, I wanted to have the data binding of the FlatList bound to an API which returns the following JSON:
[
{
name: "One",
img: "Images.one"
},
{
name: "Two",
img: "Images.two"
},
{
name: "Three",
img: "Images.three"
}
]
Of course the binding to the Card image does not work as the img is interpreted as a string.
I tried to modify the image binding to:
<Card image={JSON.parse(item.img)}>
</Card>
But this simply throw an error and the image does not render.
Simply stumped on how images would be handled in this scenario.
Any insight would be appreciated. Thanks.
If you can do some adjustment in your json, it is possible
Just keep image name inside json data
{
name: "One",
img: "one"
},
{
name: "Two",
img: "two"
},
{
name: "Three",
img: "three"
}
]
and when you want to render it you can use
import { Images } from '#configuration';
<Card image={Images[item.img]}>
</Card>
If your name property is always same as the actual image source, then I would consider using name property to extract image url like below:
import { Images } from '#configuration';
<Card image={Images[item.name.toLowerCase()]}>
</Card>

useRef([]) with dynamically created elements

I created a component with several div elements.
By adding a ?goto= parameter to the url I want to scroll the the relevant element. I now solved that with const itemsRef = useRef([]);.
My main concern now is if that's the right and performance efficient approach with itemsRef.current[element.id] = el. element.id will be unique for each element.
I also found packages such as: https://github.com/Macil/react-multi-ref
But I don't see the disadvantage of my approach yet.
Here you can find my current solution in action: https://codesandbox.io/s/scrolltoref-w5i7m?file=/src/Element.js
import React, { useRef, useEffect, useState } from "react";
import clsx from "clsx";
const blueprint = [
{
id: "3mD59WO",
name: "AUDITORIUM",
position: 0,
rooms: [
{
id: "zR8Qgpj",
name: "Audimax",
subtitle: null,
details: null,
position: 0,
elements: [
{
id: "1jLv04W",
position: 0,
type: "daily",
element: "listing_large",
properties: {
meetingId: null,
capacity: 6
}
},
{
id: "1jLv12W",
position: 1,
type: "daily",
element: "listing_large",
properties: {
meetingId: null,
capacity: 6
}
}
]
}
]
},
{
id: "4mDd9WO",
name: "FOYER",
position: 1,
rooms: [
{
id: "4R8Qgpj",
name: "Speakers Table",
subtitle: null,
details: null,
position: 0,
elements: [
{
id: "2jLv04W",
position: 0,
type: "daily",
element: "listing_large",
properties: {
meetingId: null,
capacity: 6
}
},
{
id: "2jLv12W",
position: 1,
type: "daily",
element: "listing_large",
properties: {
meetingId: null,
capacity: 6
}
}
]
}
]
}
];
export default function Query() {
const itemsRef = useRef([]);
const [currentRef, setCurrentRef] = useState();
useEffect(() => {
const scrollToRef = ref => {
window.scrollTo(0, ref.offsetTop);
};
const goto = "1jLv12W"; // This will become an URL parameter ?goto=:someID in the final version
const ref = itemsRef.current[goto];
setCurrentRef(ref); // This is needed to change the className to highlight
scrollToRef(ref); // Here I assign the ref and the component should scroll to that ref
}, []);
return (
<div key="element">
{blueprint.map(floor => (
<div key={floor.id} style={{ marginTop: 50 }}>
Floor: {floor.name} <br />
<br />
{floor.rooms.map(room => (
<div key={room.id}>
Room Name: {room.name}
<br />
{room.elements.map(element => (
<div
ref={el => (itemsRef.current[element.id] = el)}
className={clsx({
highlight:
currentRef && currentRef === itemsRef.current[element.id]
})}
key={element.id}
style={{ backgroundColor: "green", marginTop: 100 }}
>
ElementID: {element.id}
<br />
</div>
))}
</div>
))}
</div>
))}
</div>
);
}
That's the right approach, usually, you will see useRef([]) when handling multiple animations in a page, and that's exactly how it's done itemsRef.current[element.id] = el.
My main concern now is if that's the right and performance efficient approach
That's directly related to "Why Premature Optimization Is the Root of All Evil".
Premature optimization is spending a lot of time on something that you may not actually need.
You trying to optimize before you have any performance issues. Focus on delivering the product and clean code, find a time for optimization when you actually measured it.
We also don’t want to waste an enormous amount of time doing performance optimization on things that don’t matter. Many development teams get caught up in focusing on optimizing for performance and scale before they have validated their new product functionality.
useRef is basically the same as doing useState({ current: <value you pass in> });
Given your use case, what you have done is sufficient however I would change use ref to initialise with an object since that is what you are actually using as oppose to an array:
const itemsRef = useRef({});
Your code still works but may potentially give you some unexpected behaviour since assigning properties to an array can be a bit weird and is definitely not what you intend to do anyway.
For example with an array you are actually doing this:
[]["<some id>"] = el; // very weird!
vs an object:
{}["<some id>"] = el

My state open all of my submenu but i just want one submenu open

I have a left-menu and when you click on a element, the sub-menu of the element appear.
But with my actual code, when a click on a element, all of my submenu appear.
I know my method is not right, but i don't know how to do :(
My example code :
import { useState } from 'react'
export default function Menu(){
const [visibleSubCategorie, setVisibleSubCategorie] = useState(false)
const Menu = [{
name: 'Homme', link : '/homme-fr', subCategory: false
}, {
name: 'Femme', link : '/femme-fr', subCategory: [{
name: 'haut', link : '/femme-haut-fr'
},{
name: 'bas', link : '/femme-bas-fr'
}]
},{
name: 'Enfant', link : '/enfant-fr', subCategory: [{
name: 'haut', link : '/enfant-haut-fr'
},{
name: 'bas', link : '/enfant-bas-fr'
}]
}]
console.log("Menu -> Menu", Menu)
return(
<>
{Menu.map(item=>
<div>
{item.subCategory ?
<>
<button type="button" onClick={() => setVisibleSubCategorie(!visibleSubCategorie)}>{item.name}</button>
{visibleSubCategorie && item.subCategory.map(subCategorys=>
<>
<p>{subCategorys.name}</p>
</>
)}
</>
:
<a href={item.link}>{item.name}</a>
}
</div>
)}
</>
)
}``
example : when i click at the button "Femme" to see the sub-category of femme, it's like i click too on the button "Enfant".
I can create a composant and make the usestate "const [visibleSubCategorie, setVisibleSubCategorie] = useState(false)" inside and this composant inside the map but i know another method exist.
You are using the same piece of state to control all of your subCategories. A possible solution would be to useState as an array of string values for each subcategory.
const [visibleSubCategorie, setVisibleSubCategorie] = useState([])
setVisibleSubCategorie([...visibleSubCategorie, subCategorys.name])
Then check to see if that name exists in the array to know if you should show the subcategory.
{visibleSubCategorie.includes(subCategorys.name) && item.subCategory.map(subCategorys=>
You will then have to remove that item from the array when closing.
You could solve this using a method similar to what #Kyler suggested.
I suggest using a HOC, like this:
const setOpen = (setOpen, opened) => () => setOpen(!opened);
And then in your JSX:
onClick={setOpen(setVisibleSubCategorie, visibleSubCategorie)}
Note that in order for this to work, you'd have to have state for each of your sections.

Change node colour onclick react-d3-graph

I have created a very basic network graph with nodes and links between the nodes using the react d3-graph module. How could I possibly allow my users to change the colour of a node by double clicking on it?
Here are the docs I am following for the library I am using:
https://goodguydaniel.com/react-d3-graph/docs/
Note: I also have an empty on click function in my code which receives the id of the node the user clicks on.
Here is my code:
class App extends Component {
constructor(props) {
super(props)
this.state = {
data: {
nodes: [
{id: 'Harry'},
{id: 'Saly'},
{id: 'Aly'}
],
links: [
{source: 'Harry', target: 'Aly'},
{source: 'Harry', target: 'Saly'},
]
},
myConfig: {
nodeHighlightBehavior: true,
node: {
color: 'lightgreen',
size: 120,
highlightStrokeColor: 'blue'
},
link: {
highlightColor: 'lightblue'
}
}
}
}
render() {
return (
<div className="App">
<Graph
id='graph-id' // id is mandatory, if no id is defined rd3g will throw an error
data={this.state.data}
config={this.state.myConfig}
onClickGraph={onClickGraph}
onClickNode={onClickNode}
onDoubleClickNode={onDoubleClickNode}
onRightClickNode={onRightClickNode}
onClickLink={onClickLink}
onRightClickLink={onRightClickLink}
onMouseOverNode={onMouseOverNode}
onMouseOutNode={onMouseOutNode}
onMouseOverLink={onMouseOverLink}
onMouseOutLink={onMouseOutLink}
/>
</div>
);
}
}
According to the documentation, we can pass color as an attribute. All we need to do now is utilize this inside double click handler.
I believe this example will be useful.

Image will not load when trying to call it up from from local JSON file

I was able to bring in data dynamically from a local JSON file I created in RN. However, when I went back and inserted an image for each profile so that it can be displayed dynamically with their profile info, the app broke saying "The component cannot contain children. If you want to render content on top of the image, consider using ".
I am using a background for all of the profiles already, so I really don't understand what it is saying, since the images I inputted in the JSON file would be a profile image for each character. Am I even following the proper format to call up an image? Any help would be appreciated.
This is how I have my JSON File set up:
const characters = [
{ id: "1", name: "Homer Simpson", occupation: "Nuclear Safety Inspector",
url:
"https://assets.fxnetworks.com/cms/prod/shows/the-simpsons/photos/simpsons-sidebar/character-facts/Homer/swsb_character_fact_homer_288x763.png"
},
{ id: "2", name: "Marge Simpson", occupation: "Stay-at-home mom", url:
"https://assets.fxnetworks.com/cms/prod/shows/the-simpsons/photos/simpsons-sidebar/character-facts/Homer/swsb_character_fact_homer_288x763.png"},
{ id: "3", name: "Bart Simpson", occupation: "Student", url:
"https://assets.fxnetworks.com/cms/prod/shows/the-simpsons/photos/simpsons-sidebar/character-facts/Homer/swsb_character_fact_homer_288x763.png" },
{ id: "4", name: "Lisa Simpson", occupation: "Student", url:
"https://assets.fxnetworks.com/cms/prod/shows/the-simpsons/photos/simpsons-sidebar/character-facts/Homer/swsb_character_fact_homer_288x763.png" },
{ id: "5", name: "Maggie Simpson", occupation: "Baby", url:
"https://assets.fxnetworks.com/cms/prod/shows/the-simpsons/photos/simpsons-sidebar/character-facts/Homer/swsb_character_fact_homer_288x763.png" }
export default characters;
This is how I am bringing it in:
import React from "react";
import {
View,
Text,
StyleSheet,
Image,
Button,
ImageBackground
} from "react-native";
class CharacterProfiles extends React.Component {
static navigationOptions = {
title: "The Simpsons",
headerStyle: {
backgroundColor: "#53b4e6"
},
headerTintColor: "#f6c945",
headerTitleStyle: {
fontWeight: "bold"
}
};
render() {
const { item } = this.props.navigation.state.params;
return (
<View>
<ImageBackground
source={{
uri:
"https://backgrounddownload.com/wp-content/uploads/2018/09/simpsons-clouds-background-5.jpg"
}}
style={{ width: "100%", height: "100%" }}
>
<Image>{item.url}</Image>
<Text>Name: {item.name}</Text>
<Text>Occupation: {item.occupation}</Text>
<Button
title="Character Directory"
onPress={() => this.props.navigation.navigate("CharacterDirectory")}
/>
<Button
title="Homepage"
onPress={() => this.props.navigation.navigate("Home")}
/>
</ImageBackground>
</View>
);
}
}
export default CharacterProfiles;
In the same way as you've already done with your ImageBackground component, you need to use the source attribute to assign the URL of an Image. You can see examples of this in more detail in React Native's Image component documentation.
<Image
source={{uri: item.url}}
/>
Including the source URL in the content of the <Image> tag as text will have no effect. Doing this would essentially be equivalent to writing the following in HTML:
<img>https://example.com/myImage.png</img>
You're getting the warning about placing content on top of the image because React Native thinks you're trying to superimpose the URL as text on the image. Since HTML <img> elements can't do this, neither can the Image component.

Categories

Resources