I'm trying to map an array in (React js) to find out if it contains a "photographer" value, so I can display a picture saying that this specific part of the array is copyright protected (parts of these array does not contain "photographer")
This is the array I'm working with:
"collection": {
"version": "1.0",
"href": "http://images-api.nasa.gov/search?q=sun&page=1&media_type=image&year_start=2022&year_end=2022",
"items": [
{
"href": "https://images-assets.nasa.gov/image/ACD22-0003-004/collection.json",
"data": [
{
"album": [
"CAPSTONE"
],
"center": "ARC",
"title": "CAPSTONE facing the Sun (Illustration)",
"photographer": "Daniel J. Rutter",
"nasa_id": "ACD22-0003-004",
"media_type": "image",
"keywords": [
"CAPSTONE",
"NRHO",
"Cubesat",
"Artemis"
],
"date_created": "2022-02-02T00:00:00Z",
"description": "CAPSTONE, a microwave oven-sized CubeSat, will fly in cislunar space – the orbital space near and around the Moon. The mission will demonstrate an innovative spacecraft-to-spacecraft navigation solution at the Moon from a near rectilinear halo orbit slated for Artemis’ Gateway. Illustration by Daniel Rutter."
}
],
"links": [
{
"href": "https://images-assets.nasa.gov/image/ACD22-0003-004/ACD22-0003-004~thumb.jpg",
"rel": "preview",
"render": "image"
}
]
}
this is how I have mapped this array:
{data?.collection?.items?.map((items, index) => {
if(
**items.data.photographer is true (here is where I'm stuck!**
)
{
return (
*Something specific*
)
} else {
return(
something else.)}
note that I'm using
data?.collection?.items?.map((items, index) =>...
because I want to first display the {items.links}.
I also tried creating a const...
const map1 = data.collections.items.data.map(data => data);
then:
if ( map1.photographer) return ( something)
however that did not work. I have a feeling I miswrote it.
Thanks everyone for your help!
Cheers!!
Using Array.prototype.some() to identify the "photographer" property in any of the data field item.
Try like this:
function App() {
const data = {
collection: {
version: "1.0",
href:
"http://images-api.nasa.gov/search?q=sun&page=1&media_type=image&year_start=2022&year_end=2022",
items: [
{
href:
"https://images-assets.nasa.gov/image/ACD22-0003-004/collection.json",
data: [
{
album: ["CAPSTONE"],
center: "ARC",
title: "CAPSTONE facing the Sun (Illustration)",
photographer: "Daniel J. Rutter",
nasa_id: "ACD22-0003-004",
media_type: "image",
keywords: ["CAPSTONE", "NRHO", "Cubesat", "Artemis"],
date_created: "2022-02-02T00:00:00Z",
description:
"CAPSTONE, a microwave oven-sized CubeSat, will fly in cislunar space – the orbital space near and around the Moon. The mission will demonstrate an innovative spacecraft-to-spacecraft navigation solution at the Moon from a near rectilinear halo orbit slated for Artemis’ Gateway. Illustration by Daniel Rutter."
}
],
links: [
{
href:
"https://images-assets.nasa.gov/image/ACD22-0003-004/ACD22-0003-004~thumb.jpg",
rel: "preview",
render: "image"
}
]
}
]
}
};
return (
<div>
{data.collection.items.map((item, index) => {
const copyRighted = item.data.some((d) =>
d.hasOwnProperty("photographer")
);
return (
<React.Fragment key={index}>
<div>{copyRighted && "Copy Righted"}</div>
<div>{item.href}</div>
</React.Fragment>
);
})}
</div>
);
}
ReactDOM.render(<App />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<div class='react'></div>
Related
My goal here is to have the childless nodes contain hyperlinks. This is the D3 plugin I'm basing things off of: https://github.com/deltoss/d3-mitch-tree
Image Example
I'm newer to JS and JSON so I'm having difficulties on figuring out how to proceed, especially since there's little to refer to in regard to hyperlinks & JSON. If there's a better way to go about this, I'm certainly open to new ideas.
Thank you in advance
<script src="https://cdn.jsdelivr.net/gh/deltoss/d3-mitch-tree#1.0.2/dist/js/d3-mitch-tree.min.js"></script>
<script>
var data = {
"id": 1,
"name": "Animals",
"type": "Root",
"description": "A living that feeds on organic matter",
"children": [
{
"id": 6,
"name": "Herbivores",
"type": "Type",
"description": "Diet consists solely of plant matter",
"children": [
{
"id": 7,
"name": "Angus Cattle",
"type": "Organism",
"description": "Scottish breed of black cattle",
"children": []
},
{
"id": 8,
"name": "Barb Horse",
"type": "Organism",
"description": "A breed of Northern African horses with high stamina and hardiness. Their generally hot temperament makes it harder to tame.",
"children": []
}
]
}
]
};
var treePlugin = new d3.mitchTree.boxedTree()
.setData(data)
.setElement(document.getElementById("visualisation"))
.setMinScale(0.5)
.setAllowZoom(false)
.setIdAccessor(function(data) {
return data.id;
})
.setChildrenAccessor(function(data) {
return data.children;
})
.setBodyDisplayTextAccessor(function(data) {
return data.description;
})
.setTitleDisplayTextAccessor(function(data) {
return data.name;
})
.initialize();
</script>
Chain this method before .initialize():
.on("nodeClick", function(event, index, arr) {
if (!event.data.children.length) {
console.log('you clicked a child-less item', event.data);
}
})
Inside the condition, event.data is the clicked childless item. Feel free to place URLs inside those objects and use those URLs to navigate away.
Taken from the repo's /examples folder, where I found one named Advanced example with Node Click Event.
According to the comment on the same page, you can also achieve this using the options syntax:
/* const tree = [
place your data here...
]; // */
new d3.mitchTree.boxedTree({
events: {
nodeClick({ data }) {
if (!data.children.length) {
console.log('You clicked a childless item', data);
}
}
}
})
.setData(tree)
// ...rest of chain
.initialize();
// JSON File
{
"project": [
{
"id": "0",
"title": "Old Portfolio",
"images" :{
"main": "portfolio.png",
"second": ""
},
"content": ["This is one of my first few projects I made as a beginner", "At this project, I learned using JavaScript for making interactive elements like a navbar button. This project was not really something I'm proud of. Hence why I'm making a new portfolio but now with react"]
,
"tags": ["HTML5", "CSS", "JavaScript", "jQuery"]
},
{
"id": "1",
"title": "Twitter Clone",
"images" :{
"main": "twitter_clone.png",
"second": ""
},
"content": ["Project I made to improve my skills in PHP and MySQL.", "At this project, I used MySQL to store data and use PHP to alter what my website will show to the user. I've also used AJAX and JQuery for processing data from MySQL with PHP."]
,
"tags": ["HTML5", "CSS", "JavaScript", "PHP", "MySQL", "jQuery", "AJAX"]
}
]
}
// projectList is from a JSON file
// ProjectList.js
{projectList.map((project) => (
<Projects key={project.id} projectData={project}/>
))}
// Projects.js
const imagePath = "../images/";
const mainImage = imagePath + projectData.images.main
const Projects = ({projectData}) => {
<img style={{
width: "100%",
}} src={mainImage}alt="" />
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
I have a JSON file that stores the images. This is gonna be for a list of projects.
The image src is not working and I can't import an image inside the function.
I hope someone could help I am new to React
JSON should not be object, I guess in this case you can use array.
instead of using "img" you must use thumbnail, cause your object(project) has no "img" key, but has "thumbnail"->
const mainImage = imagePath + projectData.thumbnail.main
// JSON File
[
{
"id": "0",
"title": "Old Portfolio",
"thumbnail" :{
"main": "portfolio.png",
"second": ""
},
"content": ["This is one of my first few project I made as a beginner", "At this project I learned using JavaScript for making interactive elements like a navbar button. This project was not really something I'm proud of. Hence why I'm making a new portfolion but now with react"]
,
"tags": ["HTML5", "CSS", "JavaScript", "jQuery"]
},
{
"id": "1",
"title": "Twitter Clone",
"thumbnail" :{
"main": "twitter_clone.png",
"second": ""
},
"content": ["Project I made to improve my skills in PHP and MySQL.", "At this project I used MySQL to store data and use PHP to alter what my website will show to the user. I've also used AJAX and JQuery for processing data from MySQL with PHP."]
,
"tags": ["HTML5", "CSS", "JavaScript", "PHP", "MySQL", "jQuery", "AJAX"]
}
]
// projectList is from a JSON file
// ProjectList.js
{projectList.map((project) => (
<Projects key={project.id} projectData={project}/>
))}
// Projects.js
const imagePath = "../images/";
const mainImage = imagePath + projectData.thumbnail.main
const Projects = ({projectData}) => {
<img style={{
width: "100%",
}} src={mainImage}alt="" />
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
I finally found a way,
I put the images on the public folder "public/images/image.png"
and
const Projects = ({projectData}) => {
<img src={`images/${projectData.images.main}`}/>
}
For some reason I'm unable to access the "question" key within the results array. Could someone help please? This is just a side project I've started and have been tearing my hair out for hours trying to get this first basic part to work. I've only been using react and API's for about a week now and I'm super inexperienced, so any help would be appreciated.
import React from 'react'
import ReactDOM from 'react-dom'
class App extends React.Component {
constructor() {
super()
this.state = {
questionList: []
}
}
componentDidMount() {
fetch('https://opentdb.com/api.php?amount=10')
.then(resp => resp.json())
.then(resp => this.setState({ questionList: resp }))
}
render() {
return (
<div>{this.state.questionList.results[0].question}</div>
)
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
)
and here's the API data -
{
"response_code": 0,
"results": [
{
"category": "Entertainment: Film",
"type": "multiple",
"difficulty": "medium",
"question": "Which of the following James Bond villains is not affiliated with the SPECTRE organization?",
"correct_answer": "Auric Goldfinger",
"incorrect_answers": [
"Dr. Julius No",
"Rosa Klebb",
"Emilio Largo"
]
},
{
"category": "Geography",
"type": "multiple",
"difficulty": "hard",
"question": "The mountainous Khyber Pass connects which of the two following countries?",
"correct_answer": "Afghanistan and Pakistan",
"incorrect_answers": [
"India and Nepal",
"Pakistan and India",
"Tajikistan and Kyrgyzstan"
]
},
{
"category": "Entertainment: Video Games",
"type": "multiple",
"difficulty": "medium",
"question": "In Team Fortress 2, which class wields a shotgun?",
"correct_answer": "Everyone Listed",
"incorrect_answers": [
"Heavy",
"Soldier",
"Engineer"
]
},
{
"category": "Entertainment: Video Games",
"type": "multiple",
"difficulty": "easy",
"question": "Who is the leader of Team Mystic in Pokémon Go?",
"correct_answer": "Blanche",
"incorrect_answers": [
"Candela",
"Spark",
"Willow"
]
},
{
"category": "Science & Nature",
"type": "multiple",
"difficulty": "easy",
"question": "The medical term for the belly button is which of the following?",
"correct_answer": "Umbilicus",
"incorrect_answers": [
"Nevus",
"Nares",
"Paxillus"
]
},
{
"category": "Entertainment: Cartoon & Animations",
"type": "multiple",
"difficulty": "easy",
"question": "What is lost in Hawaiian and is also the name of a little girl in a 2002 film which features a alien named "Stitch"?",
"correct_answer": "Lilo",
"incorrect_answers": [
"Lolo",
"Lucy",
"Lulu"
]
},
{
"category": "Entertainment: Cartoon & Animations",
"type": "multiple",
"difficulty": "hard",
"question": "In "Gravity Falls", what does Quentin Trembley do when he is driven out from the White House?",
"correct_answer": "Eat a salamander and jump out the window.",
"incorrect_answers": [
"Leave in peace.",
"Jump out the window.",
"Release 1,000 captive salamanders into the white house."
]
},
{
"category": "Entertainment: Television",
"type": "multiple",
"difficulty": "hard",
"question": "Who was the winner of "Big Brother" Season 10?",
"correct_answer": "Dan Gheesling",
"incorrect_answers": [
"Bryce Kranyik",
"Ryan Sutfin",
"Chris Mundorf"
]
},
{
"category": "General Knowledge",
"type": "multiple",
"difficulty": "easy",
"question": "Terry Gilliam was an animator that worked with which British comedy group?",
"correct_answer": "Monty Python",
"incorrect_answers": [
"The Goodies",
"The League of Gentlemen",
"The Penny Dreadfuls"
]
},
{
"category": "Entertainment: Video Games",
"type": "multiple",
"difficulty": "easy",
"question": "In Counter-Strike: Global Offensive, what's the rarity of discontinued skins called?",
"correct_answer": "Contraband",
"incorrect_answers": [
"Discontinued",
"Diminshed",
"Limited"
]
}
]
}
Thanks!
This will surely fail, since you are calling an asynchronous action, but your render relies on that explicitly:
{this.state.questionList.results[0].question}
You are probably receiving Cannot read property 'question' of undefined
or
Cannot read property '0' of undefined
The most basic solution would be to check if the questionList actually has some data inside.
Note: questionList in an array, not an object.
render() {
if (this.state.questionList.length === 0) {
return null;
}
return (
<div>{this.state.questionList[0].results[0].question}</div>
);
}
However the best, but the longest solution would be check step-by-step that questionList has a correct structure:
{this.state.questionList[0]
&& this.state.questionList.results
&& this.state.questionList.results[0]
&& this.state.questionList.results[0].question}
As other's have noted, your API call will take a period of time, and your App will render before it is done, so your data isn't there yet when it goes to render. You're basically trying to get data that doesn't exist yet.
I like to have a loading flag on my state to show loading stuff, as well an an error flag for any errors that come in.
import React from 'react'
import ReactDOM from 'react-dom'
class App extends React.Component {
constructor() {
super()
this.state = {
questionList: {
isLoading: true,
error: null,
data: null,
}
}
}
componentDidMount() {
fetch('https://opentdb.com/api.php?amount=10')
.then(resp => resp.json())
.then(resp => this.setState(
{questionList:
{data: resp, isLoading: false, error: null}
}))
.catch(e => this.setState({questionList: {data: null, error: e, data: null}}))
}
render() {
if (this.state.questionList.isLoading)
return <Loading />
if (this.state.questionList.error)
return <Error error={this.state.questionList.error} />
return (
<div>{this.state.questionList.data.results[0].question}</div>
)
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
)
You can and should be a little smarter with your checks, and data fixing, etc, etc... but that is the gist of how I deal with it.
I also recommend wrapping up your API calls in a module. So you could say api.questions.getList().then(...) instead of having the fetch in your components, and any data conversions, or other ugly stuff can be put in those modules. It isn't really related to your question (and would probably be overkill for this anyways), but since you seem to new to react I'll throw that out there for you.
use
console.log in render()
and you will see that your state is empty, because you call async function.
There is:
Api call - it can take 1 sec, 10 sec, 20 sec etc...
call render() - your state is empty because you need to wait for API response
you will get error...
You can add some code, eg:
render() {
if (this.state.questionList.length === 0) {
return '<div>Loading...</div>';
}
return (
<div>{this.state.questionList.results[0].question}</div>
)
}
I am not sure that your results are back to the component by the time it renders. I think you need to run a check to see if the results are there. Can you try something like this and we can go from here?
{this.state.questionList.results.length > 1 && this.state.questionList.results[0].question}
So, I have to split a json, but I don't know how. I need that the name of a category goes shows in a tab. Here's a example of my json:
"tabs": [
{
"General": [
{
"created_at": "2019-11-29 11:32:11",
"name":'Test 1'
},
{
"created_at": "2019-11-29 11:32:11",
"name":'Test 2'
},
]
},
{
"One More": [
{
"created_at": "2019-11-29 15:01:55",
"name": "Test 3"
}
]
}
]
The tab code I understand (is like this: https://react-bootstrap.github.io/components/tabs/), my problem is just show "General" or "One More" on the tab name, and the name changes... I know is a silly question, but I can't find a good explanation.
Thanks for the help!
Following the docs to render one tab for each key of tabs
<Tabs defaultActiveKey="profile" id="uncontrolled-tab-example">
{
Object.keys(tabs).map(key =>(
<Tab title={key} key={key}>
Foo
</Tab>
))
}
</Tabs>
Object.keys(myObject) will provide you an array of strings representing each property of the original object
I'm attempting to incorporate video into a flat feed from GetStreamIO. My current approach is to embed a video element from Expo into the content body of the Activity UI component if the post has a video link. Starting with Youtube links only. I'm running into an issue where I'm not able to select the video url when it's available nested in props.activity.attachments. For some reason I cannot directly access the object in the videos array directly without converting the value to JSON. I referenced this StackOverflow Post for the JSON workaround.
My code to check if attachment has video url and grab it if it does
const LikeActivity = (props) => {
if (props.activity.attachments != undefined) {
console.log(props.activity.attachments)
console.log(fetchFromObject(props.activity.attachments, "og"))
var og = fetchFromObject(props.activity.attachments, "og")
var videos = fetchFromObject(og, "videos")
console.log(og)
// Can get the og object but cannot pull video url from it.
}
return (
<Activity
{...props}
Footer={
<View>
// For Now just putting this here to see the video element render. Need to pass URI from Post to element eventually.
<Video
source={{ uri: 'http://d23dyxeqlo5psv.cloudfront.net/big_buck_bunny.mp4' }}
rate={1.0}
volume={1.0}
isMuted={false}
resizeMode="cover"
shouldPlay
isLooping
style={{ width: 300, height: 300 }}
/>
<LikeButton {...props} />
</View>
}
/>
);
};
My App implementation
<StreamApp
apiKey="XXXX"
appId="XXXX"
token="XXXXXX"
>
<FlatFeed
feedGroup="timeline"
userId="user-one"
Activity={LikeActivity}
/>
</StreamApp>
Fetch From Object method
function fetchFromObject(obj, prop) {
if(typeof obj === 'undefined') {
return false;
}
var _index = prop.indexOf('.')
if(_index > -1) {
return fetchFromObject(obj[prop.substring(0, _index)], prop.substr(_index + 1));
}
return obj[prop];
}
The feed consists of a number of posts and the props.activity.attachments has the following values at runtime. Each post with a link currently has a rich snippet. The attachments value also recognizes videos vs images. I've also included an image of the feed here as a reference.
Object {
"og": Object {
"description": "Why choose one when you can wear both? These energizing pairings stand out from the crowd",
"images": Array [
Object {
"image": "https://www.rollingstone.com/wp-content/uploads/2018/08/GettyImages-1020376858.jpg",
},
],
"title": "'Queen' rapper rescheduling dates to 2019 after deciding to “reevaluate elements of production on the 'NickiHndrxx Tour'",
"url": "https://www.rollingstone.com/music/music-news/nicki-minaj-cancels-north-american-tour-with-future-714315/",
},
}
undefined
Object {
"og": Object {
"description": "Why choose one when you can wear both? These energizing pairings stand out from the crowd",
"images": Array [
Object {
"image": "https://images.wsj.net/im-21927/TOP",
},
],
"title": "How to Pair Neutrals and Bright Colors",
"url": "https://graphics.wsj.com/glider/marketreport-4a039902-7e0d-4631-ab83-6cc1931c1bc6",
},
}
undefined
Object {
"og": Object {
"description": "Serial entrepreneur Elon Musk wants to fundamentally change the way we live. But his path to success has been characterized by both great accomplishments and flirtations with failure.",
"images": Array [
Object {
"image": "https://static01.nyt.com/images/2018/08/22/us/19xp-musk-vid-2/19xp-musk-vid-2-videoSixteenByNine1050.jpg",
},
],
"title": "Elon Musk’s Highs and Lows: PayPal, SpaceX, Tesla",
"url": "https://www.nytimes.com/video/business/100000006060092/elon-musk-tesla-spacex.html",
},
}
undefined
Object {
"og": Object {
"description": "We are in a Simulation - Elon Musk",
"images": Array [],
"site_name": "YouTube",
"title": "We are in a Simulation - Elon Musk",
"type": "video.other",
"url": "https://www.youtube.com/watch?v=xBKRuI2zHp0",
"videos": Array [
Object {
"height": "360",
"secure_url": "https://www.youtube.com/embed/xBKRuI2zHp0",
"type": "text/html",
"width": "640",
},
],
},
}
Array [
Object {
"height": "360",
"secure_url": "https://www.youtube.com/embed/xBKRuI2zHp0",
"type": "text/html",
"width": "640",
},
]
Object {
"images": Array [
"https://cdn.vox-cdn.com/thumbor/OBDFDT9j-nHEpGLckE4u5ibX2qU=/1400x1400/filters:format(png)/cdn.vox-cdn.com/uploads/chorus_asset/file/13589869/edu_distance_to_the_moon.png",
"https://www.jpl.nasa.gov/images/mars/20170622/PIA01466-16.jpg",
"http://cdn.sci-news.com/images/enlarge4/image_5608_2e-Jupiter.jpg",
"https://d2r55xnwy6nx47.cloudfront.net/uploads/2018/07/SolarFull_SeanDoran_2880FullwidthLede-2880x1620.jpg",
],
}