I have a functional component which has a useState that contains the information i want to display and the images.
const [images, setImages] = useState(
[
{
"index": 0,
"img": Volleyball,
"text": ' Lorem ipsum dolor, sit amet consectetur adipisicing elit. Libero ut dolorem dolore modi esse reprehenderit assumenda error aut ducimus, aliquam repudiandae aliquid deserunt voluptatum placeat fugit explicabo dignissimos cum tempore.'
},
{
"index": 1,
'img': Gaming,
"text": ' Lorem ipsum dolor, sit amet consectetur adipisicing elit. Libero ut dolorem dolore modi esse reprehenderit assumenda error aut ducimus, aliquam repudiandae aliquid deserunt voluptatum placeat fugit explicabo dignissimos cum tempore.'
},
{
'index': 2,
'img': Coding,
"text": ' Lorem ipsum dolor, sit amet consectetur adipisicing elit. Libero ut dolorem dolore modi esse reprehenderit assumenda error aut ducimus, aliquam repudiandae aliquid deserunt voluptatum placeat fugit explicabo dignissimos cum tempore.'
}
]
)
And this is the jsx that I have in the return body with a left button that prevImage function.
return (
<div className={classes.gallary}>
<div className={classes.direction}>
<button className={classes.leftArrow} onClick={prevImage}>Left</button>
<button className={classes.rightArrow} >Right</button>
</div>
<div className={classes.images}>
{images.map(current => {
return (
<div key={current.index}>
<img src={current.img} alt="" className={classes.image} />
</div>
)
})}
</div>
</div>
);
Here is the prevImage function :
const prevImage = () => {
const currentImgArray = [...images];
const sendToBack = currentImgArray.push(currentImgArray.pop());
setImages(sendToBack)
}
This is what it looks like before clicking the button and what I am trying to do is to place the first object as the last object in the array . If the function is called I get : "TypeError: images.map is not a function"
As has been pointed out, array::push returns the new length of the array, not an array. Basically you need to rotate the array left/right.
const prevImage = () => {
// moves last image to front of array
setImages(images => [images[images.length - 1], ...images.slice(0, -1)]);
};
const nextImage = () => {
// moves first image to end of array
setImages(images => [...images.slice(1), images[0]]);
};
Array.push returns new length of the array, so concat function is to be use on here:
const prevImage = () => {
const currentImgArray = [...images];
const sendToBack = currentImgArray.concat(currentImgArray.pop());
setImages(sendToBack)
}
Updated ans:
const prevImage = () => {
setImages(prevState => {const popArr = prevState.pop();
return prevState.concat(popArr);
})
}
Related
I am trying to store some of my data in a const variable. Like I am getting FAQ section data from an API call. Like this one, I have my data in restaurant.faq and there can be multiple data so I map through it and it is working perfectly. Suppose Now I have two questions and two answers and I am getting it perfectly.
{restaurant.faq?.map((f) => (
<ListGroup.Item key={f.id}>
Question - <strong>{f.question}</strong>
<br />
Answer - <strong>{f.answer}</strong>
</ListGroup.Item>
))}
But I want to pass the same question and answer from this restaurant.faq in a const variable
Like this in rows [{question, answer}] section. How Can I do this?
const data = {
title: "FAQ",
rows: [
{
question: "Lorem ipsum dolor sit amet,",
answer: `Lorem ipsum dolor sit amet, consectetur adipiscing elit. In sed tempor sem. Aenean vel turpis feugiat,
ultricies metus at, consequat velit. Curabitur est nibh, varius in tellus nec, mattis pulvinar metus.
In maximus cursus lorem, nec laoreet velit eleifend vel. Ut aliquet mauris tortor, sed egestas libero interdum vitae.
Fusce sed commodo purus, at tempus turpis.`,
},
{
question: "Nunc maximus, magna at ultricies elementum",
answer:
"Nunc maximus, magna at ultricies elementum, risus turpis vulputate quam, vitae convallis ex tortor sed dolor.",
},
],
};
Update how to do the same with this one?
{restaurant.menu?.map((men) => (
<ListGroup.Item key={men.id}>
<Image src={men.image} alt={men.name} style={{height:'250px', width:'1800px'}} fluid />
</ListGroup.Item>
))}
const images = [
{
original: 'https://picsum.photos/id/1018/1000/600/',
},
{
original: 'https://picsum.photos/id/1015/1000/600/',
},
{
original: 'https://picsum.photos/id/1019/1000/600/',
},
];
You can do like this
const data = {
title: "FAQ",
rows: restaurant.faq?.map(({ question, answer}) => (
{ question,
answer
})
)
I have comments that i loop through:
When i click on the three dots i want there to pop a little div out with the text "repport comment".
But when i click on one of buttons they all open :
import { FaEllipsisV } from "react-icons/fa";
import "./styles.css";
import React from "react";
const data = [
{
postId: 1,
id: 1,
name: "id labore ex et quam laborum",
email: "Eliseo#gardner.biz",
body:
"laudantium enim quasi est quidem magnam voluptate ipsam eos\ntempora quo necessitatibus\ndolor quam autem quasi\nreiciendis et nam sapiente accusantium"
},
{
postId: 1,
id: 2,
name: "quo vero reiciendis velit similique earum",
email: "Jayne_Kuhic#sydney.com",
body:
"est natus enim nihil est dolore omnis voluptatem numquam\net omnis occaecati quod ullam at\nvoluptatem error expedita pariatur\nnihil sint nostrum voluptatem reiciendis et"
},
{
postId: 1,
id: 3,
name: "odio adipisci rerum aut animi",
email: "Nikita#garfield.biz",
body:
"quia molestiae reprehenderit quasi aspernatur\naut expedita occaecati aliquam eveniet laudantium\nomnis quibusdam delectus saepe quia accusamus maiores nam est\ncum et ducimus et vero voluptates excepturi deleniti ratione"
},
{
postId: 1,
id: 4,
name: "alias odio sit",
email: "Lew#alysha.tv",
body:
"non et atque\noccaecati deserunt quas accusantium unde odit nobis qui voluptatem\nquia voluptas consequuntur itaque dolor\net qui rerum deleniti ut occaecati"
},
{
postId: 1,
id: 5,
name: "vero eaque aliquid doloribus et culpa",
email: "Hayden#althea.biz",
body:
"harum non quasi et ratione\ntempore iure ex voluptates in ratione\nharum architecto fugit inventore cupiditate\nvoluptates magni quo et"
}
];
export default function App() {
const [showOptions, setShowOptions] = React.useState(false);
return (
<div className="App">
{data.map((comment, index) => (
<div key={index} className="comment-container">
{comment.name}
<button onClick={() => setShowOptions(!showOptions)}>
<FaEllipsisV />
</button>
{showOptions ? (
<div className="options">Report this comment</div>
) : null}
</div>
))}
</div>
);
}
https://codesandbox.io/s/elated-roentgen-fbjr7?file=/src/App.js:0-2121
Example of what i'd like :
You can do something like this:
export default function App() {
const [showOptions, setShowOptions] = React.useState({ id: null, status: false });
return (
<div className="App">
{data.map((comment, index) => (
<div key={index} className="comment-container">
{comment.name}
<button onClick={() => setShowOptions({ id: comment.id, status: !showOptions.status })}>
<FaEllipsisV />
</button>
{showOptions.status && comment.id === showOptions.id ? (
<div className="options">Report this comment</div>
) : null}
</div>
))}
</div>
);
}
I have a series of blog posts stored in MD files, some of these contain multiple Gist embeds in the form of script tags.
The MD contents are rendered to the page via dangerouslySetInnerHTML, and all is fine when the page is navigated to directly. However when the app's routing is used and a full page refresh doesn't happen the script tag is included in the markup, but not executed.
The following example is using the default Next.JS blog example here: https://github.com/vercel/next-learn-starter/tree/master/basics-final.
Markdown:
---
title: "Example of GIST embedding"
date: "2020-02-20"
---
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut id arcu at arcu pretium porta. Nam feugiat est ut lectus imperdiet venenatis. Ut tempus vitae lectus id vestibulum. Sed tristique est metus. Ut pretium malesuada risus. Maecenas eget diam tristique, sagittis velit ac, efficitur nisi. Quisque lectus lorem, vehicula at mi vitae, dapibus volutpat augue. Sed dignissim pharetra ligula a efficitur. In ultrices imperdiet libero. Quisque ornare erat eu elit ullamcorper faucibus. Maecenas mattis sem a mauris posuere iaculis.
<script src="https://gist.github.com/robearlam/aec15c65aaffbd5ec00a826c5cbe57ad.js"></script>
Etiam sed interdum ligula, nec tincidunt justo. Aliquam erat volutpat. Fusce in scelerisque nisl. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin venenatis lectus at ligula mollis dapibus. Praesent condimentum metus fringilla, commodo enim non, fringilla dui. Vivamus nec ligula lacinia ante semper rhoncus eu sed nisi. In ac dolor vel lorem tincidunt lacinia. Praesent quis mattis mi, at finibus velit. Etiam auctor, magna fermentum tincidunt interdum, nulla augue porttitor enim, ac lobortis felis eros id dui. Suspendisse dignissim, dui sit amet pulvinar iaculis, nisi tellus rhoncus dolor, eu gravida risus massa accumsan magna.
Page
import Layout from '../../components/layout'
import { getAllPostIds, getPostData } from '../../lib/posts'
import Head from 'next/head'
import Date from '../../components/date'
import utilStyles from '../../styles/utils.module.css'
export default function Post({ postData }) {
return (
<Layout>
<Head>
<title>{postData.title}</title>
</Head>
<article>
<h1 className={utilStyles.headingXl}>{postData.title}</h1>
<div className={utilStyles.lightText}>
<Date dateString={postData.date} />
</div>
<div dangerouslySetInnerHTML={{ __html: postData.contentHtml }} />
</article>
</Layout>
)
}
export async function getStaticPaths() {
const paths = getAllPostIds()
return {
paths,
fallback: false
}
}
export async function getStaticProps({ params }) {
const postData = await getPostData(params.id)
return {
props: {
postData
}
}
}
Lib function
export async function getPostData(id) {
const fullPath = path.join(postsDirectory, `${id}.md`)
const fileContents = fs.readFileSync(fullPath, 'utf8')
// Use gray-matter to parse the post metadata section
const matterResult = matter(fileContents)
// Use remark to convert markdown into HTML string
const processedContent = await remark()
.use(html)
.process(matterResult.content)
const contentHtml = processedContent.toString()
// Combine the data with the id and contentHtml
return {
id,
contentHtml,
...matterResult.data
}
I also have a repo showing the issue here: https://github.com/robearlam/gist-embedding-issue
Cheers!
I ran into this same problem, I found this post to be very helpful.
Basically, you create a custom code block that formats your code tags inline.
It has you use <ReactMarkdown> component to render your markdown (instead of remark) and then you use the react-syntax-highlighter library in your custom code block component.
When rendering your markdown use:
import CodeBlock from "../../components/codeblock"
<ReactMarkdown components={CodeBlock}>{your markdown data here}</ReactMarkdown>
Importing your custom codeblock component for the markdown processor.
Tom's custom code block example below:
// components/codeblock.js
import React from "react"
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"
import {dracula} from 'react-syntax-highlighter/dist/cjs/styles/prism';
const CodeBlock = {
code({node, inline, className, children, ...props}) {
const match = /language-(\w+)/.exec(className || '')
return !inline && match ? (
<SyntaxHighlighter
style={dracula}
language={match[1]}
PreTag="div" {...props}>
{String(children).replace(/\n$/, '')}
</SyntaxHighlighter>
) : (
<code className={className} {...props}>
{children}
</code>
)
}
}
export default CodeBlock
I can't figure out how to change state in my app correctly. For example, I want change 'modalStatus' key of a particular post to true, what should I write in my showModal function? I have the following data-structure:
class App extends React.Component {
constructor() {
super();
this.state = {
posts: [
{
'author': 'Adolf Hitler',
'img': 'http://www.jewishvirtuallibrary.org/images/hitler1.jpg',
'content': 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam deleniti incidunt consectetur omnis molestiae exercitationem accusamus nostrum quia libero esse maxime aliquid ducimus, placeat rem commodi. Animi cum aut odit.',
modalStatus: false
},
{
'author': 'Iosif Stalin',
'img': 'http://xn--h1aagokeh.xn--p1ai/wp-content/uploads/2016/07/46432404.jpg',
'content':'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam deleniti incidunt consectetur omnis molestiae exercitationem accusamus nostrum quia libero esse maxime aliquid ducimus, placeat rem commodi. Animi cum aut odit.',
modalStatus: false
},
{
'author': 'Napoleon Bonapard',
'img':'http://cdn.history.com/sites/2/2015/04/hith-6-things-you-should-know-about-napoleon-E.jpeg',
'content':'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam deleniti incidunt consectetur omnis molestiae exercitationem accusamus nostrum quia libero esse maxime aliquid ducimus, placeat rem commodi. Animi cum aut odit.',
modalStatus: false
},
{
'author': 'Vladimir Putin',
'img':'http://realnienovosti.com/images/148795554214.jpg',
'content':'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam deleniti incidunt consectetur omnis molestiae exercitationem accusamus nostrum quia libero esse maxime aliquid ducimus, placeat rem commodi. Animi cum aut odit.',
modalStatus: false
}
]
};
And function that is responsible for changing the state:
showModal () {
this.setState(do something)
}
Write it like this, pass a index to this function whose value you want to edit,
showModal (index) {
var posts = JSON.parse(JSON.stringify(this.state.posts));
posts[index].modalStatus = true;
this.setState({posts});
}
Check the DOC.
Or You could use the update immutability helper for this:
this.setState({
posts: update(this.state.posts, {0: {modalStatus: {$set: true}}})
})
You can do it like that:
showModal () {
var item = this.state.posts[0];
item.modalStatus = true;
this.setState({});
}
After that - React will re-render your component according to new state object.
Below is my nested object json, where i want access the properties in different react component
{
"Created":"2017-02-09",
"SenderOrReceiver":"Not developed yet",
"PageResponsible":"Yogesh Shinde",
"LastUpdated":"2017-02-09",
"ExternalLinks":[
{
"Id":null,
"Title":"Yahoo",
"Url":"http://yahoo.com"
},
{
"Id":null,
"Title":"Facebook",
"Url":"http://facebook.com"
}
],
"InternalLinks":[
{
"Id":null,
"Title":"Google",
"Url":"~/link/23199285feef4501987b5fa452e49b94.aspx"
}
],
"Appendices":[
{
"Id":null,
"Title":"React",
"Url":"~/link/23199285feef4501987b5fa452e49b94.aspx"
}
],
"ContactDetails":{
"Email":"user#gmail.com",
"Information":"Aliquam mollis, quam nec suscipit placerat, nibh est efficitur urna, in ornare mauris eros eu tortor. Nulla fermentum hendrerit mi, nec luctus nunc auctor at. Nullam sagittis posuere libero, eget imperdiet neque. Etiam ac lacus diam. Mauris sapien turpis, lobortis non eros in, porttitor dapibus ipsum.",
"Name":"user1",
"Telephone":"11234"
},
"Subject":[
"Lorem"
],
"HeadingLinks":[
{
"Id":"headinglink1",
"Title":"Heading1",
"Url":"/sv/news-page/#headinglink1"
}
]
}
Below is my server side index.cshtml (Layout)
#model intrav2.infrastructure.ViewModels.Pages.NewsPageViewModel
<div class="l-content_primary" role="main">
<div id="breadcrumb"></div>
<h2>#Html.PropertyFor(x => x.CurrentPage.Heading)</h2>
<div id="newcreatedinfo"></div>
<div>#Html.PropertyFor(x => x.CurrentPage.Media)</div>
<p class="preamble">#Html.PropertyFor(x => x.CurrentPage.Preamble)</p>
<div id="newsHeadingLinks"></div>
<p>#Html.PropertyFor(x => x.CurrentPage.MainBody)</p>
#Html.PropertyFor(x => x.CurrentPage.ExtraInformation)
<div id="newspagecontent"></div>
</div>
<aside class="l-blocks_secondary" role="complementary" id="newsSiderBar"></aside>
Now i want,
Created/SenderOrReceiver property in newcreatedinfo
External and Internal links in newspagecontent
Appendices/Contact in side content on page