Return list item with nested ternary in React.js/JSX - ternary-operator

I want my react component to return a list item depending on the type of object array that is fed to it (string array element versus non-string array element). Everything works except for the nested ternary part. The conditions are evaluated correctly, when I do <li>{console.log(listValue2)}</li> instead of <li>{listValue2}</li> , the correct value is logged. But the list item does not appear in the DOM or virtual DOM no matter which code I do. My code is also available at https://github.com/neallred/neallred/tree/master/src/components.
Any ideas?
List.jsx
import React from 'react';
export class List extends React.Component {
render(){
return (
<div>
{this.props.list.map(function(listValue, index){
return (
<div key={index}>
<h3>{listValue.title}</h3>
<p>{listValue.description}</p>
<ul>
{(typeof listValue.highlights === 'object' ?
listValue.highlights.map(function(listValue2, index2){
(typeof listValue.highlights[index2] === 'string' ?
<li>{listValue2}</li>
:
<li>{listValue2.title}</li>
)
})
:
<li>no highlights object/outside of nested conditional</li>
)}
</ul>
</div>
);
})}
</div>
);
}
}
This.props.list structure (FixturesEducation.jsx):
import React from 'react';
import { List } from './List.jsx';
...
const researchAssistant = {
title: 'Research Assistant Work',
description: `Working for Professors...`,
highlights: [
'Ensured research replicability',
'more strings here...',
'Used Stata scripts to conduct quantitative analyses'
]
};
const math = {
title: 'Mathematical Foundation',
description: 'Via several math and economics courses...',
highlights: [
'Game Theory (Econ 478)',
'more strings here...',
'Calculus I (Math 112 equivalent)'
]
};
const economics478 = {
title: 'Game Theory',
highlights: [
'several',
'strings...'
]
};
const economics459 = {
...
};
const economics388 = {
...};
const economics382 = {
...
};
const economics = {
title: 'Economics',
description: 'I learned about...,
highlights: [
economics478,
economics459,
economics388,
economics382
]
};
const politicalScience372 = {
...
};
const politicalScience376 = {
...
};
const politicalScience497r = {
...
};
const politicalScience470 = {
...
};
const politicalScience344 = {
...
};
const politicalScience = {
title: 'Political Science',
description: 'I learned a lot...',
highlights: [
politicalScience470,
politicalScience497r,
politicalScience376,
politicalScience372,
politicalScience344
]
};
const spanish = {
title: 'Spanish Language',
description: 'I obtained my Spanish Language certificate...'
};
const businessMinor = {
title: 'Business Minor',
description: 'I this minor, I learned...'
};
const FixturesEducation = {
title: 'Education',
description: 'I attended ...',
highlights: [
researchAssistant,
math,
economics,
politicalScience,
businessMinor,
spanish
]
};
export { FixturesEducation };
Code calling List component (Education.jsx):
import React from 'react';
import { List } from './List.jsx';
...
import { FixturesEducation } from './FixturesEducation.jsx';
...
export class Education extends React.Component {
render(){
return (
<div className='col-md-10 col-md-offset-1 panel' id='education'>
<h1>{FixturesEducation.title}</h1>
<List list ={FixturesEducation.highlights}/>
</div>
);
}
}

Related

How to find and print array of objects in mongoDB document

I have this document in mongoDB:
{
"_id": {
"$oid": "628f739398580cae9c21b44f"
},
"events": [
{
"eventName": "Dans",
"eventText": "Danse",
"eventDate": "010101"
},
{
"eventName": "Spill",
"eventText": "Spille",
"eventDate": "020202"
}
],
"school": "Høyskolen Kristiania"
}
I am trying to get each event (name, text and date) in their own div, but can't seem to access each "block" by their own. They are supposed to be printed as one, and only where school matches, and my intention was to make different documents for each school and filter by query from there. That though, is not an issue. I am able to get all of them as one array of objects or like
{
[dev:server] _id: new ObjectId("628f739398580cae9c21b44f"),
[dev:server] events: [ [Object], [Object] ],
[dev:server] school: 'Høyskolen Kristiania'
[dev:server] }
My API currently looks like this:
Name of course is going to be sent in by userinfo, hardcoded for testing purposes.
router.get("/", async (req, res) => {
const name = "Høyskolen Kristiania";
const schools = await mongoDatabase
.collection("tempschool")
.find()
.toArray();
console.log(schools);
res.json(schools);
});
And my client:
function EventCard({ event }) {
const { eventName, eventDate, eventText } = event;
return (
<div>
<h1>{eventName}</h1>
<h3>{eventDate}</h3>
<div>{eventText}</div>
</div>
);
}
export function SchoolPage() {
const {loading, error, data} = useLoader(
async () => await fetchJSON("/api/schools")
);
const school = data;
if (loading) {
return <div>Loading...</div>;
}
if (error) {
return (
<div>Error</div>
);
}
return (
<div>
{school.map((event) => (
<div key={event.name}>
<EventCard event={event}/>
</div>
))}
</div>
);
}
I don't know if you've created tempschool as a MongooseSchema or not. You should though, you will then query it as
const school = await TempSchool.findOne({school: "Høyskolen Kristiania"});
school.events will then give you an array of objects. You will use it on front-end as
return(
<div>
school.events.map((event) => (
<div>
<h1>{event.eventName}</h1>
<h3>{event.eventDate}</h3>
<div>{event.eventText}</div>
</div>
)
)
</div>
);

Graph won't start at zero

I'm working on a Dashboard, and I'm trying to display daily sales on a graph using mongodb. The issue that I'm having is that my graph does not start at 0, instead it starts at a number closer to the lowest number of daily sales that I entered. Also, the graph only displays the two dates that had sales, and I was wondering if there was a way to include all dates in between and following those dates? I would really appreciate any help or advice on how to solve this problem. Thank you!
OrderRouter.js
import express from 'express';
import expressAsyncHandler from 'express-async-handler';
import Order from '../models/orderModel.js';
import User from '../models/userModel.js';
import Product from '../models/productModel.js';
import {isAdmin, isAuth, isSellerOrAdmin, mailer, payOrderEmailTemplate} from '../utils.js';
orderRouter.get(
'/summary',
isAuth,
isAdmin,
expressAsyncHandler(async (req, res) => {
const dailySales = await Order.aggregate([
{
$group: {
_id: { $dateToString: { format: '%m-%d-%Y', date: '$createdAt' } },
orders: { $sum: 1 },
sales: { $sum: '$totalPrice' },
},
},
{ $sort: { _id: 1 } },
]);
res.send({ dailySales });
})
);
export default orderRouter;
DashboardScreen.js
import { useDispatch, useSelector } from 'react-redux';
import Chart from 'react-google-charts';
import { summaryOrder } from '../actions/orderActions';
import LoadingBox from '../components/LoadingBox';
import MessageBox from '../components/MessageBox';
export default function DashboardScreen() {
const orderSummary = useSelector((state) => state.orderSummary);
const { loading, summary, error } = orderSummary;
const dispatch = useDispatch();
useEffect(() => {
dispatch(summaryOrder());
}, [dispatch]);
return (
<div>
<div className="line">
</div>
<div className="background">
<div>
<h1>Dashboard</h1>
</div>
{loading ? (
<LoadingBox />
) : error ? (
<MessageBox variant="danger">{error}</MessageBox>
) : (
<>
<div className="graphs">
<div>
<h2 className="graphname">Daily Sales</h2>
{summary.dailySales.length === 0 ? (
<MessageBox>No Sale</MessageBox>
) : (
<Chart
width="100%"
height="400px"
chartType="AreaChart"
loader={<div>Loading Chart</div>}
data={[
['Date', 'Sales'],
...summary.dailySales.map((x) => [x._id, x.sales]),
]}
></Chart>
)}
</div>
</div>
<div>
</div>
</>
)}
</div>
</div>
);
}
In answer to your first question: in the Documentation for react-google-charts, there is a configuration option called: vAxis.minValue, described as:
Moves the min value of the vertical axis to the specified value; this will be downward in most charts. Ignored if this is set to a value greater than the minimum y-value of the data.
I'm betting this will help you out. In the docs, there's also an example of implementation:
vAxis: {minValue: 0}

fetching data from API in react poll

I want to fetch data from API and show frontend using react but I am getting error from frontend side which is (TypeError: answers.map is not a function ) so how can I solve this error --
MY CODE IS -
import React, { useState, useEffect } from "react";
import Poll from "react-polls";
import { getPolls } from "../helper/coreapicalls";
const MainPoll = () => {
const [polls, setPoll] = useState([]);
const [error, seterror] = useState(false);
// Setting answers to state to reload the component with each vote
const [pollAnswers, setPollAnswers] = useState([]);
useEffect(() => {
loadPoll();
}, []);
const loadPoll = () => {
getPolls().then((data) => {
if (data.error) {
seterror(data.error);
} else {
setPoll(data);
console.log(data);
}
});
};
// Handling user vote
// Increments the votes count of answer when the user votes
const handalchange = () => {
console.log("hello");
};
return (
<div className="">
<div className="container">
<h1 className="blog_heading">Poll's of the Day</h1>
<div className="row">
{polls.map((poll, index) => (
<div className="col-lg-4 col-12" key={index}>
<Poll
question={poll.question}
answers={poll.options.none}
onVote={handalchange}
/>
</div>
))}
</div>
</div>
</div>
);
};
export default MainPoll;
Data which I am getting from API is-
Here I have Question , 3 options how can I show to frontend
Error -
There is two little mistakes in the code that you show us:
the first One you imported import Polls from "./polls"; and you call <Poll noStorage question={poll.question} answers={poll.options} onVote={handleVote}/> just change Poll by Polls.
const [pollAnswers, setPollAnswers] = useState([...answers]); this didn't work because you need to pass a initial value for your state and answer is not yet initialize and accessible. just change useState([...answers]); by useState([]);
UPDATE:
you need to pass an array to answers props .
We can see in your console screenshot that the array of options has "none" as key so
try this : <Poll noStorage question={poll.question} answers={poll.options.none} onVote={handleVote}/> ("none" is a strange key...)
UPDATE
Your data object is not well formated to fit react-polls answers props.
in the npmjs doc of react-polls we can see an example of options and it's an array of object like this:
[
{ option: 'Yes', votes: 8 },
{ option: 'No', votes: 2 }
]
so based on the data console log that you add in your question it should looks like this:
[
{
createdAt: "2020-12-01T21:43:23:21.061Z",
options: {
none: [ { option: 'Yes', votes: 8 },
{ option: 'No', votes: 2 }],
student: ["12345678978945"],
teacher: ["7894567894231"]
},
question: "Are you student ot teacher",
updatedAt: "2020-12-01T21:43:23:21.061Z"
}
]
see a sandBox here working with your code (except getPolls()).
I think the issue come from the API.

Error: values.map is not a function ( why I get this error )

i am fetching details from database through Id wanted to display that into the table, but for initial purpose i wanted to just display on browser without table and stuff.. am getting values.map is not a function but when I did console.log(values), got {title: "", description: "", tags: "", photo: "", loading: false, …}
createdBlog: ""
description: ""
error: ""
formData: ""
getaRedirect: false
loading: false
photo: ""
tags: ""
title: ""
proto: Object
what to do, please help
import React, { useState, useEffect } from "react";
import "../../styles.css";
import { getoneBlog } from "../helper/coreapicalls";
import ImageHelper from "../helper/ImageHelper";
const Fullblog = ({ match }) => {
const [values, setValues] = useState({
title: "",
description: "",
tags: "",
photo: "",
loading: false,
error: "",
createdBlog: "",
getaRedirect: false,
formData: "",
});
const {
title,
description,
tags,
loading,
error,
createdBlog,
getaRedirect,
formData,
} = values;
const preload = (blogId) => {
getoneBlog(blogId).then((data) => {
//console.log(data);
if (data.error) {
setValues({ ...values, error: data.error });
} else {
// preloadCategories();
setValues({
...values,
title: data.title,
description: data.description,
tags: data.tags,
formData: new FormData(),
});
}
});
};
console.log(values);
useEffect(() => {
preload(match.params.blogId);
}, []);
return (
<div>
<div className="py-md-5 py-3">
<div className="Fullblog ">
{values.map((fullblog, index) => {
return (
<div>
<h1 className="FullblogTittle">
Founder Leandra Medine Cohen announced the news to her
employees on a Zoom call earlier this week.
{fullblog.title}
</h1>
<p className="tags">tags </p>
<img
src="https://cdn.pixabay.com/photo/2020/10/17/17/41/girl-5662873_960_720.jpg"
className="FullblogImg"
alt="img"
/>
<ImageHelper />
<p className="description">
CULTURE How to Celebrate Halloween at Home This Year From
horror movie marathons to Halloween-themed drive-in features
to virtual pumpkin carving parties, here's how to celebrate
Halloween safely this year. By Pahull Bains Date October 22,
2020 With cases on the rise in certain regions of Ontario ’s A
Little Blurry. The livestream will be viewable on demand for
24 hours for ticket holders. Get your tickets here.
</p>
</div>
);
})}
</div>
</div>
</div>
);
};
export default Fullblog;
coreapicalls code-
// get all Blogs
export const getBlogs = () => {
return fetch(`${API}/blogs`, {
method: "GET",
})
.then((response) => {
return response.json();
})
.catch((err) => console.log(err));
};
//get a Blog
export const getoneBlog = (blogId) => {
return fetch(`${API}blog/${blogId}`, {
method: "GET",
})
.then((response) => {
return response.json();
})
.catch((err) => console.log(err));
};
You can use .map() function on an Array but your state looks to be set up as an Object rather than an array.
Check these lines:
{values.map((fullblog, index) => {
&
const [values, setValues] = useState({ ... }); // This is an object
Reference
The map() method creates a new array populated with the results of
calling a provided function on every element in the calling array.
So the issue is, you are trying the map() on an object that's why it is showing you the error.
You can only use .map() on Array variables, as mentioned before.
You can simply do this:
Object.keys(values), which will make an Array with the keys of your object.
Object.keys(values).map( keys => console.log(values[key]) )
You used object destructuring on values but there is no such method as Object.prototype.map...
You can loop over Object.values(values) with map or Object.keys(values) if you want to loop over the keys.
Code:
Object.values(values).map((fullblog, index) => {
// insert code here
});

How to query a single document from a Mongodb collection with react

I'm trying to build a search bar with a react frontend and node backend, that will let me search a customer ID from a mongoDB collection, then pull all of the data from a single document down from within the collection and display it on my react app.
Currently, I am just trying to get to get the single document bit to work, if this is possible. At the moment, it pulls down the entire collection.
My current Node code:
Search router
const express = require('express');
const app = express();
const tfiPaintCodesRouter = express.Router();
const PaintInfoSchema = require('../models/PaintInfoSchema.js');
tfiPaintCodesRouter.route('/get').get(function (req, res) {
const tfipaintcode = new PaintInfoSchema(req.body);
console.log(req.body)
tfipaintcode.save()
.then(tfipaintcode => {
res.json('Got data!!');
})
.catch(err => {
res.status(400).send("unable to get data");
console.log('CustomerID is required', err.res);
});
});
tfiPaintCodesRouter.route('/').get(function (req, res) {
PaintInfoSchema.find(function (err, tfipaintcodes){
if(err){
console.log('this is an error!', err.res);
}
else {
res.json(tfipaintcodes);
}
});
});
module.exports = tfiPaintCodesRouter;
Mongo schema using mongoose.
const mongoose = require('mongoose')
var uniqueValidator = require('mongoose-unique-validator');
const Schema = mongoose.Schema;
// Create schema
const PaintInfoSchema = new Schema({
customerID: {
required: true,
index: true,
unique: true,
type: String
},
companyName: {
index: true,
type: String
},
curtainCodes: {
index: true,
type: String
},
sinageCodes: {
index: true,
type: String
},
Notes: {
index: true,
type: String
},
Method: {
index: true,
type: String
},
},{
collection: 'tfiPaintCodes'
});
PaintInfoSchema.plugin(uniqueValidator);
module.exports = mongoose.model('PaintInfoSchema', PaintInfoSchema)
My current react code is:
import React from 'react';
import { Form, FormGroup, Input, Container, Row, Col } from 'reactstrap';
import './Search.css'
import axios from 'axios'
class Search extends React.Component {
constructor(props) {
super(props)
this.state = {
searchInfo: []
};
}
handleInputChange = (event) => {
event.preventDefault();
const { value } = event.target;
console.log('Value', value)
this.setState({
query: value
});
this.search(value);
};
search = query => {
axios.get('http://localhost:3001/getData')
.then(res =>{
const searchInfo = (res.data || []).map(obj => ({
company: obj.companyName,
sinage: obj.sinageCodes,
method: obj.Method,
notes: obj.Notes}));
this.setState({ searchInfo });
})
};
componentDidMount() {
this.search("");
}
render() {
return(
<Container>
<Form>
<Row>
<Col md={{ size: 6 ,offset: 3}}>
<FormGroup className="SearchBar">
<Input onChange={this.handleInputChange} type="search" name="search" id="exampleSearch" placeholder="search" />
</FormGroup>
</Col>
</Row>
</Form>
<ul>
{this.state.searchInfo.map(function(searchInfo, index){
return (
<div key={index}>
<h1>NAME: {searchInfo.company}</h1>
<p>{searchInfo.sinage}</p>
<p>{searchInfo.method}</p>
<p>{searchInfo.notes}</p>
</div>
)
}
)}
</ul>
</Container>
);
}
}
export default Search
The code above queries mongodb, then pulls down all of the data stored in my collection, here is an image of the returned data.
Data displayed in frontend
But i want to know if it is possible to just pull down one document in that collection, so it would just display one Name: and then the other 4 bits of data.
I have the data stored in Mlab, here is a screenshot of the documents stored in my collection.
data in mongodb
Is this possible? Thanks!
The best way is to pull only one document from the DB (if you don't need more in your case).
Mongoose, as any other ORM/ODM, gives you those options:
https://mongoosejs.com/docs/api.html#model_Model.findOne
With FindOne you can search for documents but get only one (aka. "the first found") document back.
If you need a fixed number of returned documents, you can use limit(10) to, for example, return only 10 documents.
Though it appears to me that your code-snippets don't show the exact segment where do the query in Mongoose, otherwise we could have shown you what to do in your own example.

Resources