How can I access the values of the props in my component? - javascript

I have this jsx component ArticleListItem which receives data as props and displays it. When I run my web app, I get this error: Objects are not valid as a React child. How should I handle the props to access them the way I'm trying.
Here's the ArticleListItem component which throws the error:
import { Link } from 'react-router-dom';
import { Button, Icon, Item, Segment, SegmentGroup } from 'semantic-ui-react';
export default function ArticleListItem(props) {
return(
<SegmentGroup>
<Segment>
<Item>
<Item.Header>
{props.article.title}
</Item.Header>
<Item.Content>
{props.article.description}
</Item.Content>
</Item>
</Segment>
<Segment>
<span>
<Icon name='clock' /> {props.article.publishedAt}
<Icon name='newspaper' /> {props.article.author}
</span>
</Segment>
<Segment>
<span>
<Icon name='globe' /> <Button>
as={Link}
to={props.article.url}
color='teal'
floated='right'
content='View' </Button>
</span>
</Segment>
</SegmentGroup>
)
}
Here's an example of the props
{
"source": {
"id": "business-insider",
"name": "Business Insider"
},
"author": "Diamond Naga Siu",
"title": "See how much Apple pays engineers, analysts and thousands of others",
"description": "Insider analyzed thousands of Apple's H-1B visa applications to get a sense of how much it pays employees.",
"url": "http://www.businessinsider.com/see-how-much-apple-pays-engineers-analysts-and-thousands-others-2022-9",
"urlToImage": "https://i.insider.com/633222528345c90018de0060?width=1200&format=jpeg",
"publishedAt": "2022-09-28T12:00:00Z",
"content": null
}
And here's the code block where I'm passing the props to this component:
return (
<>
{props.articles && props.articles.map(article => (<ArticleListItem key={article.title} article={article} />
))}
</>
)
The idea of my web app is to fetch news from my api and to show them. I get an array of news, map over them and create an ArticleListItem for each of them.
Any help appreciated!

Your props are not inside the button tag. The ">" tag was misplaced
<Button
as={Link}
to={props.article.url}
color='teal'
floated='right'
content='View'>
Test
</Button>

Related

Submit POST to Facebook with Graph API issue

I'm a junior dev and new to Facebook for Developers, I'm struggling a bit with the Graph API. I went back and forth with the Docs, and I used the code it provided, but it doesn't seem to be fulfilling the need.
I'm making a React app, and part of it is I'd like to be able to submit a post, AKA a POST request, to the Users own Facebook Page with the text box I've made (using DevExtreme's HTML editor) I went through all the reading to target the specific users page as opposed to a Page...Page, and I'm 99% sure my syntax is ok but something is clearly off.
The goal is on the 'click' of the submit button, submit the value of the text inside the text box. You'll see in the FB.api section I have a console.log, and it is returning the 'response' - but it's just the Users name/profile ID, not any info associated with the post like the time created or the post ID. Based on that, I think I'm connected to some part of Facebook's API but it's just not the part I want! Am I doing something backwards here?
/*global FB*/
import React from 'react';
import HtmlEditor, { Toolbar, MediaResizing, Item } from 'devextreme-react/html-editor';
import Button from 'react-bootstrap/Button'
import $ from 'jquery'
const headerValues = [false, 1, 2, 3, 4, 5];
var message = $('.ql-editor .ql-blank .dx-htmleditor-content').text();
const created_time = new Date()
created_time.toUTCString();
function postSubmit() {
FB.api(
'/me',
'POST',
{ "fields":"id,name,posts", "message": message },
function(response) {
response.posts.data.push(message, created_time)
}
);
}
class Poster extends React.Component {
constructor() {
super();
this.state = {
isMultiline: true,
};
}
render() {
return (
<div className="widget-container">
<HtmlEditor
height="500px"
width="500px"
defaultValue={message}
>
<MediaResizing enabled={true} />
<Toolbar>
<Item name="undo" />
<Item name="redo" />
<Item name="separator" />
<Item
name="header"
acceptedValues={headerValues}
/>
<Item name="separator" />
<Item name="bold" />
<Item name="italic" />
<Item name="strike" />
<Item name="underline" />
<Item name="separator" />
<Item name="alignLeft" />
<Item name="alignCenter" />
<Item name="alignRight" />
<Item name="alignJustify" />
<Item name="separator" />
<Item
widget="dxButton"
options={this.toolbarButtonOptions}
/>
</Toolbar>
</HtmlEditor>
<Button onClick={postSubmit}>Click To Submit</Button>
</div>
);
}
}
export default Poster;

How to use mapping in React JS for Image

Hi guys so I'm trying to make some web page about hotel room information using React JS and I wanted to change the name, description, image of the page depending on the room type the user choose. But I don't know how to map the image, can somebody help me to do the mapping ?
I haven't make the button tag to change the room type yet.
Here's my room.js code:
import React from 'react'
import {Row, Col, Container} from "react-bootstrap"
const RoomInfo = [
{
MainPhoto:"",
RoomType:"Superior Twin",
RoomDescription:"",
LittlePhoto:'Photo1.jpg'
},
{
MainPhoto:"",
RoomType:"Double Room Twin",
RoomDescription:"",
LittlePhoto:'Photo1.jpg'
},
]
const Room = () => {
return (
<>
<Container fluid={true} className="p-0">
<Row>
<Col>
<h1 className="text-center"> Check out our room</h1>
</Col>
</Row>
</Container>
</>
)
}
export default Room
I hope I understand your question correctly.
you can do <img src={variable} /> and than assign the variable the link to the picture.
You can using map array like this to render element from an array:
...
<h1 className="text-center"> Check out our room</h1>
{
RoomInfo.map((item, i) => {
return (
<div key={i}>
<img src={item.LittlePhoto} />
</div>
);
});
}
...

Each child in a list should have a unique key prop

Here is a link to a working example of the site: https://codesandbox.io/s/eloquent-kapitsa-kk1ls
The issue I am having is with Buttons.js:
import React, { Component } from "react";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import registerIcons from "./FontAwesome";
registerIcons();
const DATA = [
{
href: "https://github.com/",
icon: ["fab", "github"],
label: "Github"
},
{
href: "https://www.linkedin.com/in//",
icon: ["fab", "linkedin"],
label: "LinkedIn"
},
{
href: "...",
icon: ["fas", "file-alt"],
label: "Resume"
},
{
href: "mailto:",
icon: ["fas", "paper-plane"],
label: "Email me"
}
];
const Icon = ({ href, icon, label }) => {
return (
<span className="button">
<a href={href} target="_self" rel="noopener noreferrer">
<FontAwesomeIcon className="icon" icon={icon} size="3x" />
<span className="icon_title">{label}</span>
</a>
</span>
);
};
class Buttons extends Component {
render() {
return (
<div>
{DATA.map(props => (
<Icon {...props} />
))}
</div>
);
}
}
export default Buttons;
I have looked through the other topics related to this issue and none are analogous to my case. I am not passing parameters to the render method - just taking an existing variable and mapping it to produce my output.
I have tried changing the Buttons render method to the code below in addition to a few other permutations of the DATA array without much progress.
<div key={DATA.label}>
{DATA.map(props => (
<Icon {...props} />
))}
</div>
I have also read through the React documentation on keys with no success.
you should change the code with this:
<div>
{DATA.map((props,i) => (
<Icon key={i} {...props} />
))}
</div>
As it is advised not to use index as a key for component. I would say add a random number and do something like below
<div>
{DATA.map((props,i) => (
<Icon key={Math.random()*1000*i} {...props} />
))}
</div>
This is rather a generic approach if you don't have any unique key in your object.
Try
<Icon {...props} key={props.href} />
From react documentation
A good rule of thumb is that elements inside the map() call need keys.
Please take a look to this documentation
https://reactjs.org/docs/lists-and-keys.html#extracting-components-with-keys
The key needs to go on like this:
<div key={DATA.label}>
{DATA.map(props => (
<Icon key={props.label} {...props} />
))}
</div>
As you probably saw in the React documentation on keys you reference, they say
The best way to pick a key is to use a string that uniquely identifies a list item among its siblings.
Each of the objects in your DATA array have unique strings and you can use any of them key={props.href} or key={props.icon[1]}. I used props.label in the answer above but the point is it doesn't have to be totally unique in all the world, it just needs to be unique compared to the other items in the list.

Decoupling delete modal from button?

I've put together a sample I am working on where I want to decouple my dialogue Modal from the delete button. I'm running into trouble trying to think of how I can restructure the components while still keeping functionality. Ideally the modal should be rendered once and be modular. Data passed into it should change during the request to show the modal.
https://stackblitz.com/edit/react-l8hbdr
Right now I believe a delete modal is created for every single button which is horribly inefficient. I've heard using references are bad and using Redux for this seems overkill. Maybe I should use a React portal?
Where should the modal be rendered from? I'd like a reusable modal and I found this guide, however I don't know where I should be storing the Modal component and how data should pass into it.
There is a problem with props drilling in your code
For example, expenses and updateExpenses are passed from <Main /> to DisplayExpenses and then passed to <DeleteExpense />, if the app is getting bigger, this will make the code hard to maintain. I think you can put const [expenses, updateExpenses] = React.useState(...) from <Main /> to <DisplayExpenses />.
import React from 'react'
import { Col, Card, Row, Button } from "antd";
import uuid from 'react-uuid'
import 'antd/dist/antd.css';
import addExpense from '../utilities/AddExpense';
import DeleteExpense from '../utilities/DeleteExpense';
const Sentencer = require('sentencer');
export default function DisplayExpenses(props) {
// move expenses from <Main /> to <DisplayExpenses />
const [expenses, updateExpenses] = React.useState([
{
"id": uuid(),
"name": Sentencer.make("{{ noun }}"),
"amount": 53.22,
},
{
"id": uuid(),
"name": Sentencer.make("{{ noun }}"),
"amount": 76.16,
},
{
"id": uuid(),
"name": Sentencer.make("{{ noun }}"),
"amount": 716.16,
},
]);
const ListOfExpenses = () => {
return expenses.map((index) => {
return (
<Col key={index.id}>
<Card
key={index.id}
title={index.name}
bordered={true}
style={{ width: "100%", border: "1px solid black" }}
actions={[
<DeleteExpense
key={index.id}
id={index.id}
name={index.name}
amount={index.amount}
updateExpensesFn={updateExpenses}
expenses={expenses} />
]}
>
<p key={index.id}>Amount: {index.amount}</p>
</Card>
</Col>
)
})
}
return (
<>
<Row gutter={[16, 8]}>
<ListOfExpenses />
<Button
type="primary"
style={{ margin: "5% 5%" }}
onClick={() => addExpense({ expenses, updateExpensesFn: updateExpenses})}
>
Add Expense
</Button>
</Row>
</>
);
}
if you want to render <DeleteModal /> only once instead of every single button, you can adjust <DeleteExpense /> slightly, make <DeleteModal /> rendered only when modalVisibleBool is true
{modalVisibleBool && (
<DeleteModal
showModal={modalVisibleBool}
onOkay={() => onConfirmDelete({
updateExpensesFn: props.updateExpensesFn,
expenses: props.expenses,
expenseToDelete
})}
cancelFn={() => onCancelDeleteModal()}
expenseToDelete={expenseToDelete}
/>
)}

Looking for a better algorithm (conditional rendering)

On my webapplication I use a json file to store my different routes, and I loop over an array inside this json file to create content, such navbar buttons.
The problem I face is that I would like to use a different icon for each value displayed from the json file, and I cannot store the icon component into the json file.
Here is my sample of code with the loop on the array contained in the json file
{props.buttons.button.map((button, index) => (
<div key={index}>
{(button.isAuth === props.isAuth || button.isAuth === 3) && (
<>
<Link to={button.to} className="link">
<ListItem button>
<ListItemIcon>
<InputIcon />
</ListItemIcon>
<ListItemText primary={button.label} />
</ListItem>
</Link>
</>
)}
</div>
))}
Here is a sample of the json file
{
"button": [
{
"label": "Home",
"isAuth": 3,
"to": "/"
},
{
"label": "About",
"isAuth": 3,
"to": "/about"
}
]
}
Currently, for each data on my json file, always the same icon component is displayed : <InputIcon />.
How can I display a different icon component for each data from the json file (such as <HomeIcon /> for the home button, <LogInIcon /> for the login one, ...) without using and if/else
Thanks
If possible you can structure the <InputIcon /> component to accept a prop and pass the label to this component.

Categories