Accessing a file through JSON object? - arrays

I have some paths in a react file that look like this:
import azureIcon from './azure.png';
import dropboxIcon from './dropbox.png';
I also have a separate JSON file that looks like this:
{
"posts": [
{
"id": 1,
"name": "azure",
"description": "blah blah",
"icon": "azureIcon"
},
{
"id": 2,
"name": "dropbox",
"description": "blah blah",
"icon": "dropboxIcon"
}
]
}
Is it possible to have it identify the variable like this? Or will it not work because currently the value of "icon" is set to a string value? What would be a good way to approach this?
Thank you!

It is impossible to do this directly, but you could do something like
const icons = { azureIcon, dropboxIcon };
const MyComponent = () => {
return (
<div>
{posts.map(post => (
/*or w/e the correct way to normally render it is*/
<img src={icons[post.icon]} />
)}
</div>
)
}

I would suggest to place images in public accessible folder. Here is example from create-react-app docs section in case you use it.
So to simplify your code you can use such approach:
Place icons in public accessible folder (let`s say we have icons folder inside)
Update your config
const posts = [
{
"id": 1,
"name": "azure",
"description": "blah blah",
"icon": "azure.png"
},
{
"id": 2,
"name": "dropbox",
"description": "blah blah",
"icon": "dropbox.png"
}
]
Show icons in such manner
const Component = (posts) => (
<React.Fragment>
{posts.map(post => <img
key={post.id}
src={process.env.PUBLIC_URL + `/icons/${post.icon}`}
/>}
</React.Fragment>
)

If I have to use icons as images I would choose the way #Kison suggests.But it is nice if you could font awesome, here it is showed how to install/import font awesome https://fontawesome.com/start and you can search icon here https://fontawesome.com/icons?d=gallery and all you have to do is paste the website says html code it is like following:
<i class="fab fa-accusoft"></i> this will render azure icon and
<i class="fab fa-dropbox"></i> this will render dropbox icon.
Here these are two icons' links:
(azure icon) https://fontawesome.com/icons/accusoft?style=brands
(dropbox icon) https://fontawesome.com/icons/dropbox?style=brands

Related

Building quiz site with react, I have 4 buttons that's an option of the question answer

I mapped the component which generated 5 questions and obviously 20 buttons. My problem now is that the first 4 buttons on each row always have the same ID when I try to get each button clicked so I can check if the correct answer was selected. I need every button to have a unique ID. I've tried different ID functions but none seem to work, I think the problem is from my logic and not the ID itself.
import React from "react";
export default function Question_page(props) {
const [triviaApi, setTriviaApi] = React.useState()
const styles = {
backgroundColor: props.isHeld ? "#59E391" : "grey"
}
return (
<div className="main-question-container">
<div className="question">
<h3>{props.my_items.question}</h3>
</div>
<div className="question-button">
<button onClick={props.holdAnswer}>{props.my_items.incorrect_answers[0]}</button>
<button onClick={props.holdAnswer}> {props.my_items.incorrect_answers[1]}</button>
<button onClick={props.holdAnswer}>{props.my_items.correct_answer}</button>
<button onClick={props.holdAnswer}>{props.my_items.incorrect_answers[2]}</button>
</div>
</div>
)
}
The App components below
import QuestionPage from "./components/Question_page";
import React from "react";
import {nanoid} from 'nanoid'
import {BrowserRouter as Router, Route, Routes} from "react-router-dom"
import JsonData from "./JsonData";
export default function App() {
const [colorState, setColorState] = React.useState({
isClicked: true
})
const jsonDataElement = JsonData.map(item => {
return item.results.map((innerItem,index) => {
const myID = Math.random()
return (
<QuestionPage
key={myID}
my_items={innerItem}
isHeld={innerItem.isClicked}
holdAnswer={() => holdAnswer(myID)}
/>
)
})
})
function holdAnswer(ID) {
// here is where I want to check if every bottom has a different ID so I can change the colour and save the variable to check if the answer was right during my "check answer" click. The issue is, that the first button on the row gives me the same ID, I need to get a different ID on every button which contains the answer option so I can run this function
console.log(ID)
}
return (
<Router>
<NavBar/>
<Routes>
<Route path="/" element={<Start/>}/>
<Route path="/question" element={
<div>
{jsonDataElement}
<div className="check-answer-container">
<button className="check-answer">Check answer</button>
</div>
<hr/>
</div>
}/>}/>
</Routes>
</Router>
);
}
The JSON data im using
export default [{
"response_code": 0,
"results": [
{
"category": "Science: Computers",
"type": "multiple",
"difficulty": "medium",
"question": "Which of these is the name for the failed key escrow device introduced by the National Security Agency in 1993?",
"correct_answer": "Clipper Chip",
"incorrect_answers": [
"Enigma Machine",
"Skipjack",
"Nautilus"
]
},
{
"category": "Science: Computers",
"type": "multiple",
"difficulty": "medium",
"question": "In the server hosting industry IaaS stands for...",
"correct_answer": "Infrastructure as a Service",
"incorrect_answers": [
"Internet as a Service",
"Internet and a Server",
"Infrastructure as a Server"
]
},
{
"category": "Science: Computers",
"type": "multiple",
"difficulty": "medium",
"question": ".rs is the top-level domain for what country?",
"correct_answer": "Serbia",
"incorrect_answers": [
"Romania",
"Russia",
"Rwanda"
]
},
{
"category": "Science: Computers",
"type": "multiple",
"difficulty": "medium",
"question": "What was the first Android version specifically optimized for tablets?",
"correct_answer": "Honeycomb",
"incorrect_answers": [
"Eclair",
"Froyo",
"Marshmellow"
]
},
{
"category": "Science: Computers",
"type": "multiple",
"difficulty": "medium",
"question": "The name of technology company HP stands for what?",
"correct_answer": "Hewlett-Packard",
"incorrect_answers": [
"Howard Packmann",
"Husker-Pollosk",
"Hellman-Pohl"
]
}
]
}]
You're only setting myID once right now so all buttons are receiving the same ID - you need to set it for each button instead of once for the whole QuestionPage.
You could probably make a function on Question_page that returns Math.random and then call that from id={} on each button

React reading nested JSON data fails when loads or refresh

I am developing a screen to show data based on search results. Below is the JSON output.
When I click search result below component is called. In the result screen i need id, name and table1, table2 data.
Table1 and Table2 are nested outputs and these will be displayed in React Table or Data Grid (next step)
Issue: Unable to render StudyData.table1.name
Options Tried
1. UseEffect()
UseEffect() able to read StudyData.studyname but not StudyData.table1.name
Assigned to a variable
Assigned to a state
2. Render
tried using map for subdocuments
Finding: It fails only first time load and refresh. I tried to comment -> save->load -> remove the comments and save. Then works (as component is loaded). I am missing something during the first time load or refresh. Please help
[
{
"id": "DD3",
"studydate": "DDD",
"studydescription": "DD3 Description",
"studyname": "DD3",
"table1": [
{
"no": "1",
"name": "DD3 Name",
"date": "Krishna",
"description\r": "1111\r"
},
{
"no": "2",
"name": "DD3 Nam2",
"date": "Test2",
"description\r": "2222\r"
},
{
"no": "3",
"name": "DD3 Name3",
"date": "Test3",
"description\r": "3333"
}
],
"table2": [
{
"No": "2",
"Study Field1": "21",
"Study Field2": "22",
"Study Field3\r": "23"
}
],
"table3": [
{
"No": "3",
"Study Field5": "T31",
"Study Field6": "T32",
"Study Field7": "T33",
"Study Field 8\r": "T34"
}
],
"_rid": "QeNcANZFTTIKAAAAAAAAAA==",
"_self": "dbs/QeNcAA==/colls/QeNcANZFTTI=/docs/QeNcANZFTTIKAAAAAAAAAA==/",
"_etag": "\"33002e92-0000-0200-0000-5fa6fe320000\"",
"_attachments": "attachments/",
"_ts": 1604779570
}
]
COMPONENT CODE
import React, { useEffect } from "react";
import api from "./UploadStudyFilesapi";
import { DataGrid } from "#material-ui/data-grid";
export default function StudyDisplay(props) {
let myData = props.Study;
const [StudyData, setStudyData] = React.useState([]);
const [Table1Rows, setTable1Rows] = React.useState([]);
useEffect(() => {
// Update the document title using the browser API
api.getStudy(myData.studyname).then((json) => setStudyData(json));
console.log(StudyData.studyname); //works
//console.log(StudyData.table1.no) //doesn't work
let myTable = StudyData.table1;
console.log(myTable);
setTable1Rows(StudyData.table1);
console.log(Table1Rows);
}, [myData]);
return (
<div>
{StudyData.length === 0 ? (
<h1>Loading...</h1>
) : (
StudyData.map((item) => (
<div key={item.studyname}>
{item.studyname}
{/* DOESNT WORK first brose or refresh*/}
{item.table1.map((key2) => (
<div>
{console.log(key2.name)}
{key2.name}
{/* Want to pass Key2 to DataGrid or React-Table */}
{/* <DataGrid rows={key2} columns={{field1:"No"}} /> */}
</div>
))}
</div>
))
)}
</div>
);
}
Thanks for your support. I added conditional rendering based on search selection in parent component. That resolved all the issues

How to display Fontawesome icons using Unicode and React?

I'm experimenting with React and want to display a list of Fontawesome icons.
I have a JSON file that has the data set about as such:
{
"icons": [
{
"name": "Glass",
"id": "glass",
"unicode": "f000",
"created": 1,
"filter": [
"martini",
"drink",
"bar",
"alcohol",
"liquor"
],
"categories": [
"Web Application Icons"
]
},
etc
I can iterate through this and return and print each point of data, but can't figure out how to display the actual icons.
I have tried using unicode as such:
return(
<div>
<ul>
<li>
<span>{data.name}</span>
<i className="fa">{data.unicode}</i>
</li>
</ul>
</div>
)
But it just prints the unicode value.
Would anyone know if it's possible to render the icon this way?
Convert the number to a string first, by calling String.fromCharCode.

How to output datocms graphql query with an array inside multiple posts

I am using the DatoCMS portfolio gatsby cloud autogenerated template. I have been able to successfully change some models in DataCMS that reflect in my graphQL playground, I then can adjust my code to reflect those changes. Now this model is for posts so there is multiples of them, now the part I am getting stuck on is, I have added a modular component to each post, which creates an array in the graphQL returned data, and I can't for the life of me figure out how to map thorough it when I am already mapping through all the posts that it is contained in.
Here is my code, and I am trying to output the data from details.task
import React from 'react'
import { Link, graphql } from 'gatsby'
import Masonry from 'react-masonry-component'
import Img from 'gatsby-image'
import Layout from "../components/layout"
const IndexPage = ({ data }) => (
<Layout>
{/* <Masonry className="showcase"> */}
{data.allDatoCmsPricing.edges.map(({ node: pricing }) => (
<div key={pricing.id} className="">
<figure className="card">
{/* <Link to={`/works/${work.slug}`} className="card__image">
<Img fluid={work.coverImage.fluid} />
</Link> */}
<h6 className="card__title">
<Link to={`/works/${pricing.slug}`}>{pricing.title}</Link>
</h6>
<div className="card__description">
<p>{pricing.excerpt}</p>
</div>
{{pricing.details.task}}//Tasks go here, I know this wont work
</figure>
</div>
))}
{/* </Masonry> */}
</Layout>
)
export default IndexPage
export const query = graphql`
query IndexQuery {
allDatoCmsPricing(sort: { fields: [position], order: ASC }) {
edges {
node {
id
title
slug
excerpt
details{
task
}
coverImage {
fluid(maxWidth: 450, imgixParams: { fm: "jpg", auto: "compress" }) {
...GatsbyDatoCmsSizes
}
}
}
}
}
}
`
and here is the resulting data from a playground query
{
"data": {
"allDatoCmsPricing": {
"edges": [
{
"node": {
"id": "DatoCmsPricing-1913799-en",
"title": "Silver",
"slug": "flyer-1",
"excerpt": "European minnow priapumfish mosshead warbonnet shrimpfish bigscale. Cutlassfish porbeagle shark ricefish walking catfish glassfish Black swallower.",
"details": [
{
"task": "Client Consultation"
},
{
"task": "S.M.A.R.T Goal Setting"
},
{
"task": "Fitness Assessment"
},
{
"task": "Client Centered Exercises"
},
{
"task": "1-2 Sessions per week"
}
]
}
},
{
"node": {
"id": "DatoCmsPricing-1913807-en",
"title": "Packaging 1",
"slug": "packaging-1",
"excerpt": "Efficiently unleash cross-media information without cross-media value. Quickly maximize timely deliverables for real-time schemas. Dramatically maintain clicks-and-mortar.",
"details": []
}
},
{
"node": {
"id": "DatoCmsPricing-1913806-en",
"title": "Stationery 1",
"slug": "stationery-1",
"excerpt": "User experience deployment MVP ecosystem direct mailing. Creative iteration early adopters research & development partnership buyer investor innovator success scrum project validation graphical user interface termsheet mass market.",
"details": []
}
}
]
}
}
}
With help from another source the following is what I was looking for to output the tasks
<ul className="details-list">{pricing.details.map(detailEntry => {
return <li key={detailEntry.id}><span>{detailEntry.task}</span></li>
})}</ul>

Right way to parse Redux state props - using super json objects

Following my trip with React and Redux, I'm facing a problem, simple in appearance, but hard to solve : I'm setting my Redux state with a very big JSON object. Those datas are retrieved from an async call. When I'm setting it, I created an entry in my reducer with
let initialState = {
pages: []
}
Then, I'm putting different pages, with their params and datas into this pagesarray. So far so good, the state is well updated.
BUT, my different app pages use only parts of it as you can imagine. For instance, I have a page named Gallery which might need my state to look like this :
"pages": [
{
"component":"Gallery",
"key": "gallery",
"title": "Galerie photos",
"url": "/galerie-photos",
"sections": [
{
"component": "Gallery",
"params": {
"images": [
{
"id": 1,
"src": "http://lorempicsum.com/futurama/627/300/1",
"alt": "alternate text"
},
{
"id": 2,
"src": "http://lorempicsum.com/futurama/500/400/2",
"alt": "alternate text"
},
{
"id": 3,
"src": "http://lorempicsum.com/futurama/400/320/3",
"alt": "alternate text"
},
{
"id": 4,
"src": "http://lorempicsum.com/futurama/800/500/4",
"alt": "alternate text"
},
{
"id": 5,
"src": "http://lorempicsum.com/futurama/320/300/5",
"alt": "alternate text"
},
{
"id": 6,
"src": "http://lorempicsum.com/futurama/420/360/6",
"alt": "alternate text"
}
]
}
}
]
}
]
In my GalleryContainer, I'm requesting only the images property as this is the only concern of my Gallery component. I'm able to retrieve this data with no problem. Testing with the following code returns the desired images array :
But as far as I tested this, the images are not retrieved by my Gallerycomponent : when console logging on the component side, I got undefined, and on the container side, no problem.
I tested something different : I set a galleryImages property via the reducer, and set it with the gallery images directly. This worked.
The questions are : Why doesn't it work in the first case, and do in the second ? Do I have to work only with datas that are set as state properties only ? Can't I have a "super" json set in my state to work with directly ?
Thanks to light me up on this one :)
// Component
import React from 'react'
const Gallery = ({images}) => (
<div>
{images.map((image, key) =>
<div key={key} className="image-element-class" style={card}>
<img src={image.src} alt={image.alt} style={imageStyle}/>
</div>
)}
</div>
)
const card = {
width: 'calc((100% / 3) - (15px / 1.5))',
marginBottom: '15px',
boxSizing: 'border-box'
}
const imageStyle = {
width: '100%'
}
export default Gallery
// Container
import { connect } from 'react-redux'
import Gallery from '../../components/pages/Gallery'
const getImages = state => {
return {
images: state.data.pages.filter(page => page.component === 'Gallery' &&(
page.sections.filter(section => section.component === 'Gallery' &&(
section.params.images
))
)),
}
}
const mapStateToProps = state => {
return getImages(state)
}
const GalleryContainer = connect(
mapStateToProps,
{}
)(Gallery)
export default GalleryContainer
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react-dom.min.js"></script>

Resources