I have an array like this in React data file and I'm using the .map() method to load JSON data in component ProjectItem.js.
When I type {console.log("title" + projects[0].title)} and log data Projecttitle1 appears on console. How should I take the data, render that data on my web-app itself in functional component? (Projecttitle1 to show on the web-app)
Data.json
{
"projects": [
{
"title": "Projecttitle1",
"category": "frontend development",
"description": "",
"desktop": [],
"mobile": []
}
]
}
ProjectItem.js
import React from 'react';
import './ProjectItem.scss';
import useWindowWidth from '../../Hooks/useWindowWidth.js';
import { projects } from '../../data'
import desktopImage from '../../Assets/Images/Projects/Desktop/123.jpg';
import mobileImage from '../../Assets/Images/Projects/Mobile/123_square.jpg'
const ProjectItem = ({ viewProject }) => {
const imageUrl = useWindowWidth() >= 650 ? desktopImage : mobileImage;
const { windowWidth } = useWindowWidth();
return(
<div className="projectItem" style={{ backgroundImage: `url(${ imageUrl })`}}>
{windowWidth >= 650 &&(
<>
<div className="title">
{projects.map((data, key)=>{
console.log(key);
return(
<div key={key}>
{data.title}
</div>
);
})}
</div>
<div className="viewProject">{viewProject}</div>
</>
)}
</div>
);
};
export default ProjectItem
Console:
I've tried some attemps to import json file and then deconstruct from parsed json. Now when I run npm the data still isn't printing on web-app. Would there be possible solution to this?
attempt1:
import data from '../../data'
const { projects } =() => JSON.parse(data)
attempt2:
import data from '../../data'
const {projects} =() => JSON.parse(JSON.stringify(data))
You are trying to deconstruct from json file which is basically a string representation of your object.
you need to import it, and then deconstruct from a parsed json
solution for this would be:
import data from '../../data'
const { windowWidth } = useWindowWidth();
const { projects } = JSON.parse(data)
return(
<div className="projectItem" style={{ backgroundImage: `url(${ imageUrl })`}}>
{windowWidth >= 650 &&(
<>
<div className="title">
{projects.map((data, key)=>{
console.log(key);
return(
<div key={key}>
{data.title}
</div>
);
})}
</div>
<div className="viewProject">{viewProject}</div>
</>
)}
</div>
);
Related
So I'm trying to show locale of German in my React app with dayjs but is not working, here is my code, i tried to add locale('de') but that is not doing the job, so i don't know what to try next. I'm trying to learn how to do it, and I don't know if i need to import a locale or it does it take it from 'dayjs'
import React, { Fragment, useContext, useEffect, useState } from 'react';
import dayjs from 'dayjs';
import { getMonth } from '../../utils/calendar/dayjs';
import GlobalContext from '../../context/calendar/GlobalContext';
import styles from '../../styles/Calendar.module.scss';
function SmallCalendar() {
const [currentMonthIdx, setCurrentMonthIdx] = useState(dayjs().month());
const [currentMonth, setCurrentMonth] = useState(getMonth());
useEffect(() => {
setCurrentMonth(getMonth(currentMonthIdx));
}, [currentMonthIdx]);
const { monthIndex, setSmallCalendarMonth, setDaySelected, daySelected } =
useContext(GlobalContext);
useEffect(() => {
setCurrentMonthIdx(monthIndex);
}, [monthIndex]);
function getDayClass(day) {
const format = 'DD-MM-YY';
const nowDay = dayjs().format(format);
const currDay = day.format(format);
const slcDay = daySelected && daySelected.format(format);
if (nowDay === currDay) return styles.day_active;
else if (currDay === slcDay) return styles.day_selected;
else return '';
}
return (
<div className={styles.minicalendar}>
<header className={styles.calendar_header}>
<p
style={{ color: 'var(--color-active)' }}
className='text-gray-500 font-bold'>
{dayjs(new Date(dayjs().locale('de').year(), currentMonthIdx)).format(
'DD MMMM YYYY'
)}
</p>
</header>
<div
className={`grid grid-cols-7 grid-rows-6 ${styles.minicalendar_body}`}>
{currentMonth[0].map((day, i) => (
<span key={i} className='text-sm py-1 text-center'>
{day.format('dd').charAt(0)}
</span>
))}
{currentMonth.map((row, i) => (
<Fragment key={i}>
{row.map((day, inx) => (
<button
key={inx}
onClick={() => {
setSmallCalendarMonth(currentMonthIdx);
setDaySelected(day);
}}
className={`py-1 w-full ${getDayClass(day)}`}>
<span className='text-sm'>{day.format('D')}</span>
</button>
))}
</Fragment>
))}
</div>
</div>
);
}
export default SmallCalendar;
You need to first import the locale at the top of your file.
import 'dayjs/locale/de'
Then you can set the global locale to de
dayjs.locale(‘de’)
import dayjs from 'dayjs';
import <plugin-name> from 'dayjs/plugin/<plugin-name>';
dayjs.extend(<plugin-name>);
This is how you can import any plugin into your react code.
Ex:
import dayjs from "dayjs";
import isSameOrBefore from "dayjs/plugin/isSameOrBefore";
dayjs.extend(isSameOrBefore);
Below is my code, the React app is connected to Node js and the data of comment are saved when submit but it's not working for StarRating component.
The comment data is saved in the db table but not the rating
Please pass setRating in starComponent as props
Like below:
<StarRating rating={rating1} updateRating={(e) => setRating1(e)}
onChange={e => setRating1(e.target.value)}></StarRating>
Now you will get updateRating as props in starComponent. So update rating form star component like below:
import React, { useState} from "react";
import { FaStar } from 'react-icons/fa';
const StarRating = ({rating, updateRating}) =>{ // Here you will get setRating state(State of app component) in props
// const [rating, setRating] = useState(null); // not needed this state here. Update rating value in state which comes form props
const [hover, setHover] = useState(null);
return <div>
<p>Rate your experience from 0 to 5 stars</p>
{[... Array(5)].map((star, i)=>{
const ratingValue= i + 1;
return (
<label>
<input
type="radio"
name="rating"
value={rating}
onClick={() =>updateRating(ratingValue)} /> // Update `updateRating` state which comes from app component.
<FaStar
className="star"
color={ratingValue <= (hover || rating) ? "#11C4B0" : "#D3D3D3"}
size={40}
onMouseEnter={() =>setHover(ratingValue)}
onMouseLeave={() =>setHover(null)}
/>
</label>
);
})}
</div>
}
export default StarRating;
You will get updated state in rating1 in app component if any changes occurred from starComponent.
I think the Problem is that you are accessing the rating state in App component but the real state with the value is the rating state of StarRating component. Also, you have passed the props onChange and value to StarRating component but The Props concept is different than the HTML Attributes concept so you definitely need to look into that. Anyway, the possible Solution can be...
import * as React from 'react';
import './App.css';
import StarRating from './StarRating';
import StarRating2 from './StarRating2';
import StarRating3 from './StarRating3';
import { TextArea } from 'semantic-ui-react';
import AlertDialogSlide from './confirmation';
import Dialog from '#mui/material/Dialog';
import DialogActions from '#mui/material/DialogActions';
import DialogContent from '#mui/material/DialogContent';
import DialogContentText from '#mui/material/DialogContentText';
import Slide from '#mui/material/Slide';
import Button from '#mui/material/Button';
import { useState } from "react";
const Transition = React.forwardRef(function Transition(props, ref) {
return <Slide direction="up" ref={ref} {...props} />;
});
function App() {
const [open, setOpen] = React.useState(false);
const [comment, setComment] = useState("");
const [rating1, setRating1] = useState("");
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
const onSubmitForm = async e => {
e.preventDefault();
try {
const body = { rating1, comment };
const response = await fetch("http://localhost:5000/feedback", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body)
});
window.location = "/";
} catch (err) {
console.error(err.message);
}
};
return (
<form onSubmit={onSubmitForm} >
<div className="App">
<img src='solavievelogo.png'></img>
<hr/>
<h2>Leave a feedback!</h2>
<StarRating setRating={setRating1} />
<hr2/>
<StarRating2></StarRating2>
<hr2/>
<StarRating3></StarRating3>
<hr2/>
<p>Please leave a comment about your experience below:</p>
<TextArea placeholder=' Type your comment here...'
value={comment}
onChange={e => setComment(e.target.value)}
></TextArea>
<br/>
<button class="Button" type='submit' variant="outlined" onClick={handleClickOpen}><span class="Button-inner">SEND FEEDBACK</span> </button>
<Dialog
open={open}
TransitionComponent={Transition}
keepMounted
onClose={handleClose}
aria-describedby="alert-dialog-slide-description"
>
<DialogContent>
<img src='confirm.png'></img>
<DialogContentText id="alert-dialog-slide-description">
<p>Thank you for your message!</p>
<p> We will be in contact soon..</p>
</DialogContentText>
</DialogContent>
<DialogActions >
<button class="Button" type='submit' onClick={handleClose} ><span class="Button-inner">Close</span> </button>
</DialogActions>
</Dialog>
</div>
</form>
);
}
export default App;
StarRating Component
import React, { useState} from "react";
import { FaStar } from 'react-icons/fa';
const StarRating = ({setRating}) =>{
const [hover, setHover] = useState(null);
return <div>
<p>Rate your experience from 0 to 5 stars</p>
{[... Array(5)].map((star, i)=>{
const ratingValue= i + 1;
return (
<label>
<input
type="radio"
name="rating"
value={ratingValue}
onClick={() =>setRating(ratingValue)} />
<FaStar
className="star"
color={ratingValue <= (hover || rating) ? "#11C4B0" : "#D3D3D3"}
size={40}
onMouseEnter={() =>setHover(ratingValue)}
onMouseLeave={() =>setHover(null)}
/>
</label>
);
})}
</div>
}
export default StarRating;
I fetched json data with async await and i wanted to save the fetched data in a variable in order to be able to use it with a map in my component,
the data comes in properly inside the function - i checked with an alert , and also in the variable inside the function it does display all the data , but somehow the variable outside the function returns empty .
here is some code:
both alerts in the following code return the right data.
export let fetchPosts = [];
export async function FetchPosts() {
await axios.get('https://jsonplaceholder.typicode.com/posts').then(
res => {
alert(JSON.stringify(res.data))
fetchPosts = JSON.stringify(res.data);
alert(fetchPosts)
}
).catch(err => {
alert('err');
})
}
import { fetchPosts } from '../services/post';
import { FetchPosts } from '../services/post';
export default function Posts() {
function clickme() {
FetchPosts()
}
return (<>
<button onClick={clickme}>Click me</button>
{fetchPosts.map((post, index) => (
<div key={post.id} className="card" style={{ 'width': '16rem', 'display': 'inline-block', 'margin': '5px' }}>
<div className="card-body">
<h6 className="title">{post.title}</h6>
<p className="card-text">{post.body}</p>
</div>
</div>
))}
</>)
}
State is the issue
React doesn't automatically reload on your singleton fetchPosts.
Instead, try...
export function FetchPosts() {
return axios.get('https://jsonplaceholder.typicode.com/posts');
}
then
import { useState } from 'react';
import { FetchPosts } from '../services/post';
export default function Posts() {
const [posts, setPosts] = useState([]);
function clickme() {
FetchPosts().then(res => {
setPosts(res.data);
});
}
return (<>
<button onClick={clickme}>Click me</button>
{posts.map((post, index) => (
<div key={post.id} className="card" style={{ width: '16rem', display: 'inline-block', margin: '5px' }}>
<div className="card-body">
<h6 className="title">{post.title}</h6>
<p className="card-text">{post.body}</p>
</div>
</div>
))}
</>)
}
https://codesandbox.io/s/jolly-almeida-q4331?fontsize=14&hidenavigation=1&theme=dark
If you want global state, that's another topic you should dive into entirely but you can do it with a singleton, you just need to incorporate it with hooks and an event emitter. I have a bit of a hacked version of this here https://codesandbox.io/s/react-typescript-playground-forked-h8rpu but you should probably stick to redux or mobx or AppContext which is more of a popular pattern.
I create a login button that onClick logs the user in and then the generated information is stored in the local storage, but I keep getting an "Expected onClick listener to be a function, instead got a value of string type. I am using reactJS to do so.
// Global Navigation Bar
import { connect } from "react-redux";
import React, { Component } from "react";
import cognitoUtils from "lib/cognitoUtils";
import "assets/css/Base.css";
import Avatar from "#material-ui/core/Avatar";
import Tooltip from "#material-ui/core/Tooltip";
import AccountCircleOutlinedIcon from "#material-ui/icons/AccountCircleOutlined";
import AccountCircleIcon from "#material-ui/icons/AccountCircle";
const mapStateToProps = state => {
return { session: state.session };
};
class SignInOut extends Component {
onSignOut = e => {
e.preventDefault();
cognitoUtils.signOutCognitoSession();
};
state = {
on: true
};
toggle = () => {
this.setState({
on: !this.state.on
});
};
render() {
return (
<div>
<button className="profile_button" onClick={this.toggle}>
{this.state.on && (
<div>
{this.props.session.isLoggedIn ? (
<div>
<a
className="Home-link"
href="/home"
onClick={this.onSignOut}
>
<Tooltip title="Profile">
<Avatar className="profile_icon">
<AccountCircleIcon className="profile_icon_in" />
</Avatar>
</Tooltip>
</a>
</div>
) : (
<div>
<a
className="Home-link"
href={cognitoUtils.getCognitoSignInUri()}
onClick="/home"
>
<Tooltip title="Profile">
<Avatar className="profile_icon">
<AccountCircleOutlinedIcon className="profile_icon" />
</Avatar>
</Tooltip>
</a>
</div>
)}
</div>
)}
</button>
</div>
);
}
}
export default connect(mapStateToProps)(SignInOut);
Because you are passing String type to onClick
onClick="/home"
You need to pass a function as stated in the error. something like you did before
onClick={this.onSignOut}
So I have a component(Posts) in which a loop through all the posts from the Database. In the component, I 'embedded' another component(PostItem) so I dont have to create a different component for viewing individual entries. Now inside the PostItem component I have another component with the name of 'PostGallery'.
This is the current code that I have in PostItem.js file:
import React from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import PostGallery from '../posts/PostGallery';
const PostItem = ({
post: { _id, text, name, files, avatar, user, likes, comments, date },
}) => (
<article className={_id}>
<Link to={`/posts/${_id}`}>
<div id="carouselExampleIndicators" className="carousel slide" data-ride="carousel">
<div className="carousel-inner">
{files.slice(0, 5).map((file, index) => (
<PostGallery key={index} post={file} />
))}
</div>
</div>
</Link>
</article>
);
PostItem.propTypes = {
post: PropTypes.object.isRequired,
};
export default connect(
null, null
)(PostItem);
When posting an entry the user can post URL from images separated by comma which is working just fine. The problem comes when displaying it in the front-end.
This is what I have in my PostGallery component:
import React from 'react';
import PropTypes from 'prop-types';
const PostGallery = ({
post: { files }
}) => {
return (
<div className="">
{post.files.length > 0 ? (
post.files.map(file => (
<img key={file} src={file} alt="" />
))) : (
<p>No images found</p>
)
}
</div>
);
};
PostGallery.propTypes = {
post: PropTypes.object.isRequired,
};
export default PostGallery;
I believe this should be easy but somehow its just now working and the console it's not trowing me any errors related to it. So if you guys can help...
Thanks!