Scroll to element when clicking table of contents - reactjs

In React, how can I scroll to a heading on the page, when the corresponding heading is clicked in my table of contents?
I parse my markdown document to generate a TOC:
const toc = [
{ id: 'lorem', title: 'Lorem' },
{ id: 'ipsum', title: 'Ipsum' },
{ id: 'dolor', title: 'Dolor' }
];
I then render this TOC in render()::
{ toc.map((entry) => {
return (
<li key={entry.id}>
{entry.title}
</li>
);
})}
When I click on an entry in my TOC, I would like the page to scroll to the h2 element with that id. How?
The examples I have seen all use ref. But I am not sure how to use ref in my case, where the TOC is created dynamically at runtime and hence the refs would need to be created dynamically? I cannot add them to my document's elements, since they are generated by markdown-to-jsx.

You need to add IDs to your Markdown headers in your Markdown files and you can add IDs with this syntax:
### Lorem {#lorem}
Then in your React code you render the TOCs with link tag linking to header IDs:
{ toc.map((entry) => {
return (
<li key={entry.id}>
<a href={`#${entry.id}`}>{entry.title}</a>
</li>
);
})}
To read more about Markdown ID syntax: https://www.markdownguide.org/extended-syntax/#heading-ids

Related

How to display images from json URL when the images key has two object values

This is my first stackoverflow post....be kind
I am building a react app where I want to display an image from a array of objects but the "images:" object has two objects inside example:
[
{ value: "all", label: "All sets" },
{
value: "base1",
label: "Base",
series: "Base",
printedTotal: 102,
total: 102,
legalities: { unlimited: "Legal" },
ptcgoCode: "BS",
releaseDate: "1999/01/09",
updatedAt: "2020/08/14 09:35:00",
images: {
symbol: "https://images.pokemontcg.io/base1/symbol.png",
logo: "https://images.pokemontcg.io/base1/logo.png",
},
},]
my question is how would I access the inner object to display just the "logo:" object?
my assumption is to use a combination of .map and Object.keys() but I'm unsure how to do it.
mycode is below...
import React from "react";
import setOptions from "../data/sets";
export default function SetOverview() {
const sets = setOptions;
return (
<div>
{sets.map((set) => {
return (
<div key={set.value}>
<h2>{set.label}</h2>;<p>Number of cards: {set.printedTotal}</p>
<p>Release date: {set.releaseDate}</p>
</div>
// image to be placed here
);
})}
</div>
);```
ma friend. Welcome to Stack Overflow, and no- you will not be treated with kindness. That being said,
If you are sure about the keys that are being passed in the dataset, i.e.: objName.objItem.images.logo, then all you need to do is,
Check if the images key exists in that object (because your first object doesn't have it, so I suspect there may be a reason for that).
Load the image's logo value inside that div you've specified.
To achieve this, all you need to do is:
set.images?.logo && <img src={set.images.logo} />
And voila, you shall have your image. The question mark checks if key exists.

Display nested JSON data using React

I'm displaying a Facebook feed, I've mapped the array that I've got from a JSON file to display the data, and so far so good.
let feedDisplay = feedArray.map((fbPost, index) => {
console.log(fbPost.attachments)
return (
<div key={index} >
<img src={fbPost.full_picture} />
<p>
{fbPost.message}
</p>
</div>
);
});
Now I want to display the data I get from fbPost.attachments which is an object with an array containing yet another object. I don't know what method I should use to access and display this.
{
data: [
{
description: 'some description',
media: { image: { src: 'source' } },
title: 'title',
},
],
};
What I want to display is everything inside data - description, media and title.

Making reusable component for array data in reactjs

I want to make a footer component in react with a heading and several links under it like in the image.
Also I want to pass only an array for the links like the following.
const FooterLinksData = [
{
link1: "Insolvers",
link2: "How it works?",
link3: "I'm looking for job",
link4: "I'm looking to hire",
},
{
link1: "Features",
link2: "Pricing",
link3: "Schedule a Demo",
},
];
My code:
return (
<>
<li>
<a href="/" className="footer_link">
{props.data[`link${props.num + 1}`]}
</a>
</li>
// I have written this li tag for times in my code
// props.data is the array I passed using the parent
// props.num is the number (0 in this case) to get link1 from
// the object
</>
);
My problem is that first obj under the array has 4 items while the second one only have 3. Is there any way to make a reusable component for it?
You can add the title inside the json and use it to bracke. Something like
const FooterLinksData = [
{
"title":"some title",
"links":[
"Insolvers",
"How it works"
]
},
{
"title":"some other title",
"links":[
"other Insolvers",
"other How it works"
}]
];
so then you will do something like:
FooterLinksData.map(({title, links}) => ({
<div>
<div>{title}</div>
<ul>{links.map(link => <li>{link}</li>)}</ul>
</div>
})
})
If you ask this question, I assume you use FooterLinksData[x].link1, FooterLinksData[x].link2, FooterLinksData[x].link3 ..... to display your links.
You could change your code to use the map() function instead, not having to deal with a fixed number of links.
Can't really help with code since you didn't posted how you render your links.

dynamic import of images react

I am trying to dynamically render images from a local folder within my project
The object structure looks like this
{
id: 2,
text: 'How would you describe your level of influence in management of the farm?',
type: 'cardChoice',
choices: [
{
id: 1,
text: 'I am the primary decision maker',
questionId: 'Hm?',
value: 'I am the primary decision maker',
image: '1.jpg',
},
{
id: 2,
text: 'I hent',
questionId: 'Hrm?',
value: 'I',
image: '2.jpg',
},
{
id: 3,
text: 'I arm',
questionId: '?',
value: 'Irm',
image: '3.jpg',
},
],
},
In my component I select the folder that contains the images const baseUrl = '../../assets/images/CNA'
After that, in my return I try to render the images
<img src={`${baseUrl}'${questionChoice.image}'`} alt={questionChoice.text} />
The page renders, but my image isn't loading and it's showing my alt instead
Heres my full component
const CardChoiceQuestions = ({ cardChoiceArray, currentAnswer, updateCurrent, submitAnswer }) => {
const { id, value } = currentAnswer
const baseUrl = '../../assets/images/CNA'
return (
<ButtonContainer>
{cardChoiceArray.map(questionChoice => {
return (
<Button
active={questionChoice.id === id}
type="button"
key={questionChoice.id}
onClick={() => {
const answer = { id: questionChoice.id, value: questionChoice.value }
updateCurrent(answer)
submitAnswer()
}}
>
<p>{questionChoice.text}</p>
<img src={`${baseUrl}${questionChoice.image}`} alt={questionChoice.text} />
</Button>
)
})}
</ButtonContainer>
)
}
I don't have my laptop in front of me but a few things I noticed. Do you need a slash "/" after your base url? Also, the string concatenation should be completed in one set of brackets after the $ sign. Not sure if that's the issue try a few console.log(string path) amd verify it is going where you think it is. It looks like the path may be wrong. You may be better off conditional rendering images as opposed to building a dynamic url but either way it should render on change.
<img src={`${baseUrl}/${questionChoice.image}`} alt={questionChoice.text} />
use like this
Leaving this here in case someone comes across this...
<img src={require(`../../assets/images/CNA/${questionChoice.image}`)} alt={questionChoice.text} />
Not sure why I can't use ${baseUrl} but this works for now.

How to display an array of objects inside the html template in Angular 2?

I am building web app that will have a list of 3d models. I’m doing it for a practice purposes, in order to gain some initial knowledge of angular 2.
Each listed model, will have name, main picture, category, and a slider (array of images).
Model data array is:
export var MODELS: Model[] = [{
id: 1,
name: 'Model 1',
image: 'app/img/models/model-1.jpg',
category: 'Cat 1',
slides: [
{ alt: 'Model 1 front view' , url: 'app/img/models/model-2.jpg' },
{ alt: 'Model 1 rear view' , url: 'app/img/models/model-2.jpg' },
{ alt: 'Model 1 side view' , url: 'app/img/models/model-2.jpg' }
]
},
{
id: 2,
name: 'Model 2',
image: 'app/img/models/model-2.jpg',
category: 'Cat 2',
slides: [
{ alt: 'Model 2 front view' , url: 'app/img/models/model-2.jpg' },
{ alt: 'Model 2 rear view' , url: 'app/img/models/model-2.jpg' },
{ alt: 'Model 2 side view' , url: 'app/img/models/model-2.jpg' }
]
}
];
Service that is used for proper displaying of certain model is:
#Injectable()
export class ModelService {
getModels(): Promise<Model[]> {
return Promise.resolve(MODELS);
}
getModel(id: number): Promise<Model> {
return this.getModels()
.then(models => models.find(model => model.id === id));
}
}
Model detail’s page template is:
<div *ngIf="model">
<h2>{{model.name}} details!</h2>
<img [src]="model.image" alt="{{model.name}}"/>
<div>{{model.slides}}</div>
</div>
These are Mostly stuff that I used from: https://angular.io/docs/ts/latest/tutorial/
However, when I try to use simplest way to display slides array into model-detail page, it shows [object Object]. I read that this is might be a common issue in angular 2, that can be resolved by using custom pipes. Unfortunately, I have no clue how to write one for this certain case.
General question will be: How to properly display array of objects (slides) on html template, and wrap them separately into img tag.
Here is plunker example link: http://plnkr.co/edit/HVo3dtGprMHsPYeyRWBR?p=preview
Thanks in advance,
That's because your slides property is in fact an Object, it's an array so displaying the property alone will simply display 'object'. What you need to do is iterate over the slides property and separately create img divs:
<img *ngFor="let slide of model.slides" [alt]="slide.alt" [src]="slide.url" />
this is what your updated template would look like from your plunkr:
<ul class="models">
<li *ngFor="let model of models" (click)="gotoDetail(model)">
<img *ngFor="let slide of model.slides" [src]="slide.url"/>
{{model.name}},{{model.category}}
</li>
</ul>
You could use *ngFor in an img tag I have included some of my practice code to show you what I mean.
<div class="col-md-6" *ngFor="let picture of imageUrl; let i = index; trackBy: trackByFn">
<div class="portfolio-item"
style="padding-bottom: 10px;">
<a (click)="galleryOpen = false;componentIndex = i;" data-toggle="dropdown" href="#" name="gal2">
<img class="img-portfolio img-responsive" src={{picture}} height="350" width="455"
style="height: 350px; max-width: 455px;">
</a>
</div>
</div>
The *ngFor in this case could just a easily be placed in the img tag. I hope this helps you out.

Resources