Parse tags in react - javascript

I have created object like that
export const homeObjOne ={
lightBg: false,
lightText: true,
lightTextDesc: true,
topLine:'Explore DrukBox', // - working correctly
headLine: 'Unlimited printing <br> with us',
description: 'Lets <br> begin!', // - output: Lets <br> begin!(with br)
buttonLabel: 'Get Started',
imgStart: '',
img: './assets/svg-1.svg',
alt: 'DrukBox'
}
and bringing it to component like that
function HeroSection({
lightBg,topLine,lightText,lightTextDesc,headLine,description,buttonLabel,img, alt, imgStart
}) {
return (
<div className={lightBg ? 'home__hero-section' : 'home__hero-section darkBg'}>
<div className="container">
<div className="row home__hero-row"
style={{display:'flex',flexDirection: imgStart === 'start' ? 'row-reverse' : 'row'}}
>
And so on
<div className="home__hero-img-wrapper">
<img src={img} alt={alt}/>
</div>
</div>
</div>
</div>
)
}
but in the object my html code not parses i tried all types ',",`
import {homeObjOne} from './Data'
function Home() {
return (
<div>
<HeroSection {...homeObjOne} />
</div>
)
}
export default Home
thats how i import object

You have created addPagesObjOne as a JS Object.
To access the properties within this object and assuming addPagesObjOne has been:
Imported into the component with your JSX or
Within the component file
Then to correctly reference a property see this example:
<img src={img} alt={alt}/>
will become
<img src={addPagesObjOne.img} alt={addPagesObjOne.alt}/>
Update:
I can see that you have provided an update to how you have laid out your code, I created a quick sandbox here your code works fine. Maybe your assest is not in the correct place?

Related

I am wondering why my useEffect data is empty on first render when I populate it on first render using useEffect

I am creating an app using the REST countries API and I make an API call on the first render using useEffect hook and populate my useState array with the data that I need. When I try accessing this data in the return statement for the component it reads undefined. I even tried adding a ternary operator to first check if the data is empty and if not output it but it still reads undefined but If I comment out the code and refresh the page the data become populated and can then uncomment the code for it to show and if I were to refresh the page again the data reads as undefined. I am extremely confused as to why this is happening so any help is much appreciated.
My js file:
const CountryInfo = () => {
const [data, setData] = useState([{}])
let countryName = window.location.pathname;
countryName = countryName.replace('/', '');
countryName = countryName.split('%20');
countryName = countryName.join(' ');
console.log(countryName)
useEffect(() => {
axios.get(`https://restcountries.com/v3.1/name/${countryName}`).then(response => {
console.log(response);
setData([{
name: countryName,
image: response.data[0].flags.png,
nativeName: response.data[0].name.nativeName.nld,
population: response.data[0].population,
region: response.data[0].region,
subRegion: response.data[0].subregion,
capital: response.data[0].capital[0],
borderCountries: response.data[0].borders,
topLevelDomain: response.data[0].tld[0],
currencies: response.data[0].currencies,
languages: response.data[0].languages,
}])
})
},[])
console.log(data)
return(
<div className='country-info-content'>
<Link to='/' className='info-button'>
<button className='button-info'>BACK</button>
</Link>
<div className='data-info'>
<img src={data[0].image} className='flag-img'/>
<div className='country-name'>
<span className='name'>{data[0].name}</span>
<div className='info-description'>
<div>
<div>
<span>Native Name:</span> {data[0].nativeName.common}
</div>
{/* {data?
<div>
<div>
<span className='title'>Native Name:</span> {data.nativeName.common}
</div>
<div>
<span className='title'>Population:</span> {data.population.toLocaleString(undefined)}
</div>
<div>
<span className='title'>Region:</span> {data.region}
</div>
<div>
<span className='title'>Sub Region:</span> {data.subRegion}
</div>
<div>
<span className='title'>Capital:</span> {data.capital}
</div>
</div>:null} */}
{/* {data ?
<div>
<span>Native Name: </span>{data[0].nativeName.common}
</div>: null
} */}
</div>
<div className='right-info'>
<div>
<span className='title'>Top Level Domain:</span> {data.topLevelDomain}
</div>
<div>
<span className='title'>Currency:</span> {data.topLevelDomain}
</div>
<div>
<span className='title'>Languages:</span> {data.topLevelDomain}
</div>
</div>
</div>
</div>
</div>
</div>
)
}
export default CountryInfo;
You have a data mapping error. You are setting your Data incorrectly when trying to set the native name in your data array.
you have:
setData([
{
...
nativeName: response.data[0].name.nativeName.nld,
...
}
]);
and return
<div>
<span className='title'>Native Name:</span> {data.nativeName.common}
</div>
But the data structure returned by the api looks different, eg:
data: Array(12)
0: Object
name: Object
common: "Eswatini"
official: "Kingdom of Eswatini"
nativeName: Object
eng: Object
ssw: Object
Change it to this instead:
setData([
{
...
nativeName: response.data[0].name.common,
...
}
]);
and
<div>
<span>Native Name:</span> {data[0].nativeName}
</div>
useEffect will trigger AFTER your page is rendered for the first time, that's why data is undefined the first time component renders.
You'll need to handle it and the ternary operator is a common practice:
return data ? <div>...</div> : null;
or
return data ? <div>...</div> : <div>Loading...</div>;
UPDATE:
The error message is triggered by reading common property of undefined. The only place where you do this is
data[0].nativeName.common
This means that data[0] exists, but nativeName is undefined. nativeName stores the value of response.data[0].name.nativeName.nld,.
You should double check if data returned from the API has expected format and response.data[0].name.nativeName.nld is set.
UPDATE2:
Like Zeno noticed in the comment, default value for data is [{}], and that will always evaluate to true in ternary operator.
Why not make the default undefined until data is fetched?
Also make sure you refer to the results as data[0] as this is where you store the response. Or simplify your code a bit by doing:
setData({
name: countryName,
image: response.data[0].flags.png,
nativeName: response.data[0].name.nativeName.nld,
population: response.data[0].population,
region: response.data[0].region,
subRegion: response.data[0].subregion,
capital: response.data[0].capital[0],
borderCountries: response.data[0].borders,
topLevelDomain: response.data[0].tld[0],
currencies: response.data[0].currencies,
languages: response.data[0].languages,
})
There's no need to store an array in there.

Using keys to call an array for an item list. React.js

I would like to say that this is my first time using Stack Overflow and I apologize if I don't explain this well because I am not sure how to word it.
I am trying to make a resume with a worklist on my website. The thing is I have some that have one bullet point and others with multiple points. I want to call a prop that will allow me to update the array on Resume.js but declare generalize it so it will create a list, using the array for each individual item.
I declare:
let job = []
Because I get an error stating it is undefined, but I would like to use a prop or something like it to call it down to create different arrays for each time I call func. ResumeWorkItem.
function ResumeWorkItem(props)
{
{/*Trying to use JobList to create the array but I am not sure how to call it lower down.*/}
let job = []
const JobList = job.map((job, index) =>
<li key={index}>
{job.toString()}
</li>
);
return(
<>
<div className="res__work">
<div>
<h2 className='res__work__title'>
{props.title}
</h2>
</div>
<div>
<h3 className='res__work__jobtitle'>
{props.jobtitle}
</h3>
</div>
<div className='res__work__info'>
<ul>{JobList}</ul> {/*This is where I call JobList, but I want to set up job in Resume.js .*/}
</div>
</div>
</>
);
}
Here is where I want to call the array in file Resume.js:
<section className="res-work-exp">
<ResumeWorkItem
title = 'Title 1'
jobtitle = 'Job Title 1'
{/* This is where I want to call array 1*/}
/>
<ResumeWorkItem
title='Title 2'
jobtitle='Job Title 2'
{/* This is where I want to call array 2*/}
/>
I apologize if I didn't explain this well enough. I put a few comments to see if that will help get my point across.
I've made JobList into a function to take in list of items that could be mapped as you've suggested and then call it from ResumeWorkItem. You could also move ResumeWorkItem to App.js and import JobList if you want.
Consider the following sample:
App.js
import React from 'react';
import './style.css';
import { ResumeWorkItem } from './Resume.js';
export default function App() {
return (
<section className="res-work-exp">
<ResumeWorkItem
title="Title 1"
jobtitle="Job Title 1"
joblist={[1, 2, 3]}
/>
<ResumeWorkItem title="Title 2" jobtitle="Job Title 2" />
</section>
);
}
Resume.js
import React from 'react';
export const JobList = (jobs) =>
jobs.map((job, index) => <li key={index}>{job.toString()}</li>);
export function ResumeWorkItem(props) {
return (
<>
<div className="res__work">
<div>
<h2 className="res__work__title">{props.title}</h2>
</div>
<div>
<h3 className="res__work__jobtitle">{props.jobtitle}</h3>
</div>
<div className="res__work__info">
<ul>{props.joblist ? JobList(props.joblist) : ''}</ul>
</div>
</div>
</>
);
}

How to get a src image via js?

I want to get the src image and bind it to my img tag, I'd create it in JS file and I imported, but nothing happened, first file is About.vue and the second one is my utils file
<template>
<div>
<Header></Header>
<main>
<section v-if="this.showAlert">
<b-alert show variant="success">
<h4 class="alert-heading">Well done!</h4>
<p>
This web-app was made by Gabriel Nunes, he did it all by himself.
All these buttons and headers that you saw on the app, was made by
him too.
</p>
<hr />
<p class="mb-0">
If you need anything from him, please contact via social netorks.
Social networks:
<img
:src="this.showImg.facebook.src"
:width="this.showImg.facebook.width"
:height="this.showImg.facebook.height"
/>
</p>
<p class="mb-1">
<img
:src="this.showImg.github.src"
:width="this.showImg.github.width"
:height="this.showImg.github.height"
/>
</p>
</b-alert>
</section>
<section v-if="!this.showAlert">
<b-alert show variant="secondary">
<h4 class="alert-heading">Well done!</h4>
<p>
Aww yeah, you successfully read this important alert message. This
example text is going to run a bit longer so that you can see how
spacing within an alert works with this kind of content.
</p>
<hr />
<p class="mb-0">
Whenever you need to, be sure to use margin utilities to keep things
nice and tidy.
</p>
</b-alert>
</section>
</main>
</div>
</template>
<script>
import Header from "./Header.vue";
import { pathImgObj } from "../../utils.js";
export default {
components: {
Header,
},
data() {
return {
showImg: {},
showAlert: Boolean,
};
},
created() {
this.showAlert = confirm("Are you sure about this?");
this.showImg = { ...pathImgObj };
},
methods: {},
};
</script>
<style>
</style>
Utils file js
export const config = {
home: 'Home',
anime: 'Animes',
faq: 'FAQs',
about: 'About'
}
export const pathImgObj = {
facebook: {
src: `./assets/img/facebook.png`,
width: '30px',
height: '30px'
},
github: {
src: `./assets/img/github.png`,
height: '30px',
width: '30px'
}
}
Expected result: get the src, width and height from utils file and pass it to my About.vue
How can I do this?
My results:
When a URL is required or imported, Webpack processes the URL, and decides what to do with it. For image URLs, Webpack finds the image, transforms it (e.g., image scaling and optimization), puts the result in an output directory, and returns the result's URL (e.g., dist/img/foo.abcd123.jpg).
vue-loader automatically requires only static URLs of <img>.src:
<img src="#/assets/foo.jpg"> ✅
<img :src="'#/assets/' + imgUrl1"> ❌
<img :src="imgUrl2"> ❌
export default {
data() {
return {
imgUrl1: 'foo.jpg',
imgUrl2: '#/assets/foo.jpg',
}
}
}
Dynamically bound <img>.src must be manually required either in the binding value or in the <script> block:
<img :src="require('#/assets/' + imgUrl1)"> ✅
<img :src="require(imgUrl2)"> ✅
<img :src="imgUrl3"> ✅
export default {
data() {
return {
imgUrl1: 'foo.jpg',
imgUrl2: '#/assets/foo.jpg',
imgUrl3: require('#/assets/foo.jpg'),
}
}
}
Since the URLs in the utils file are dynamically bound in the template, vue-loader does not require them, and thus they're treated as static assets in public/. For example, a static URL of ./assets/foo.jpg refers to public/assets/foo.jpg.

Nested Image Array Fails to Load

I'm relatively new to react and javascript (I'm usually backend Java). I'm currently trying to make an image gallery, where the subsections are clicked on and thumbnails of the images within each section are displayed. The thumbnails can then be clicked on and open a lightbox (I'm utilizing simple-react-lightbox for this and am on the latest version).
It works, but inconsistently. Sometimes when I click on the thumbnail, instead of throwing up the lightbox and being able to click through the images, it takes me directly to the full sized image.
My nested array with the image data, (imports of images omitted)
const GALLERIES =[
{
name: 'Beaded Jewelry',
id: 'beadwork',
description: 'placeholder',
resources:[
{
id: 1,
thumbnail: bluependant,
url: blue,
title: 'Blue Swarovski Pendant'
},
{
id: 2,
thumbnail: greenpendant,
url:green,
title: 'Green Swarovski Pendant'
}
]
},
{
name: 'Wire Jewelry',
id: 'wirewrapped',
description: 'placeholder #2',
resources:[
{
id: 'wire1',
thumbnail: wire1Thumb,
url: wireWrap1,
title: 'placholder 1'
},
{
id: 'wire2',
thumbnail: wire2Thumb,
url:wireWrap2,
title: 'placholder 1'
}
]
}
];
export default GALLERIES
And the js that I'm trying to make work consistently.
import React from 'react';
import '../css/gallery.css';
import '../css/jewelry_main.css';
import GALLERIES from '../data/galleries';
import SimpleReactLightbox from "simple-react-lightbox";
import { SRLWrapper } from "simple-react-lightbox";
import {Link } from 'react-router-dom';
const Gallery = props =>{
const{thumbnail, url, title } = props.subgallery;
return(
<div className="gallery">
<a href={url} data-attribute="SRL">
<img src={thumbnail} alt={title} />
</a>
</div>
)
}
const JewelryGallery = ({match}) =>{
const gallery = GALLERIES.find(({ id }) => id === match.params.keyword)
return(
<div>
<div className="frosted">
<p>{gallery.description}</p>
</div>
<SimpleReactLightbox>
<SRLWrapper>
{
gallery.resources.map((SUBGALLERY) =>{
return(
<Gallery key = {SUBGALLERY.id} subgallery={SUBGALLERY} />
)
})
}
</SRLWrapper>
</SimpleReactLightbox>
</div>
);
}
export default JewelryGallery;
Any insight or wisdom would be greatly appreciated! Thank you!
UPDATE EDIT: I noticed something, the first subgallery I click into will always present with the lightbox, but the second one, consistently fails and instead goes directly to the fullsize of whichever image I have clicked on. (It doesn't matter which of the two I pick first, the second always fails.) But I can't discern why the lightbox would not get applied to the second gallery I select.
There are only two things I can see that differ from the documentation for the simple-react-lightbox package.
First thing is, with the latest version, you only need to use the <SRLWrapper> component. You have both the <SRLWrapper> and the <SimpleReactLightbox> component in use. Perhaps try getting rid of the old version if you have the latest version of the package installed.
Second thing is the structure of your Gallery component return has the div wrapping the elements. I'm not sure if this would cause any problems but, to get as close as possible to the example in the docs you could try using a fragment instead of a div.
const{thumbnail, url, title } = props.subgallery;
return(
<>
<a href={url} data-attribute="SRL">
<img src={thumbnail} alt={title} />
</a>
</>
)
I haven't used the package so this is a bit of speculation. Hope it leads you in the right direction though.
EDIT
I think I misunderstood this library a bit. You do need both of those components. It looks like if you want to display full size images, you would do it the way you have it currently. However, if you want to use the lightbox feature with the nav at the bottom you would need to do something like:
<SimpleReactLightbox>
<SRLWrapper>
<div id="content-page-one" className="container content">
<div className="row">
{
gallery.resources.map((SUBGALLERY) =>{
return(
<Gallery key = {SUBGALLERY.id} subgallery={SUBGALLERY} />
)
})
}
</div>
</div>
</SRLWrapper>
</SimpleReactLightbox>
And then you would use div instead of an anchor tag:
<div className="col-md-6 col-12 col-image-half">
<img src={thumbnail} alt={title} />
</div>
This is pulled from the Code Sandbox examples they have. I would take a closer look there and see if they have the exact setup you're looking for. Notice also that they are using the Bootstrap styling framework as well, so in order for those styles to work you would need to install bootstrap to your dependencies.

Vuejs computed properties that depend on other, asynchronous, computed properties

In my Vuejs app I need to pass two computed properties to a component called avatar: an image surce and a string.
The problem is that not all items have a picture, and when they don't, vuejs throws an error because it cannot read property apples of undefined (because album_id is undefined).
The error is being thrown from that very long-winded src property in the avatar component, below:
<template>
<div class="apples">
<div id="mast" class="f3 b bb b--black-10">
<h2 class="ttc">Apple's List</h2>
</div>
<div id="content">
<li v-for="apple in apples" class="list-item">
<avatar :src="apple[ 'album_id '][ 'apples' ][ '256' ]" :size="50" :appletype="apple.type"></avatar>
</li>
</div>
</div>
</template>
<script>
import Avatar from './Avatar.vue';
import Apples from '#/api/apples';
export default {
name: 'apples',
asyncComputed: {
apples: {
async get() {
const apples = await Apples.getAll();
return apples.data;
},
default: []
}
},
components: {
Avatar
}
};
</script>
I need to somehow treat the data that I receive from the api before I use it in the html template, but I am unsure as to how to proceed. Creating a separate pictures array within the get() function just seems wrong.
Using v-if and v-else to check if there is a src property to pass down also seems very clumsy.
Do I create another, separate, computed method that iterates through my list of items and gets the picture src if the item has one?
I would suggest that you need to create getters for your apple sauce.. er.. source.. er.. src :)
<template>
<div class="apples">
<div id="mast" class="f3 b bb b--black-10">
<h2 class="ttc">Apple's List</h2>
</div>
<div id="content">
<li v-for="apple in apples" class="list-item">
<avatar :src="getAvatar(apple, 256)" :size="50" :appletype="apple.type"></avatar>
</li>
</div>
</div>
</template>
<script>
import Avatar from './Avatar.vue';
import Apples from '#/api/apples';
export default {
name: 'apples',
methods: {
getAvatar: function(obj, id) {
return obj.album_id.apples[ id ] | ''
}
},
asyncComputed: {
apples: {
async get() {
const apples = await Apples.getAll();
return apples.data;
},
default: []
}
},
components: {
Avatar
}
};
</script>
This allows you to create a graceful fallback with whatever arguments and implementation you choose.

Categories

Resources