Rendering specific Content from json - javascript

So, Hello My problem is this. I have a C-class Component that is 'maping content' that is located in data.json I will add more content later but, in C class I have a button that is currently pushing me to the Payment page, I want when the button is pressed, that it renders the content(image, price, class) only that content from json into the Payment page where I can style it once again that would be basically it. Thanks in Advance
data.json
[
{
"id":0,
"class":"A-Class",
"Info": "A is the cheapest one ",
"imgA":"./ModImages/Aclass.jpg",
"textA":"fdsd",
"trefuA":"fdsd",
"optionA":"fdsd"
},
{
"id":1,
"imgB":"./ModImages/Bclass.jpg",
"classB":"B-Class",
"priceB":"$46,400",
"textB":"fdsd",
"trefuB":"fdsd",
"optionB":"fdsd"
},
{
"id":2,
"classC":"C-Class",
"imgC":"./ModImages/Cclass.jpg",
"priceC":"$46,400",
"textC":"fdsd",
"trefuC":"fdsd",
"optionc":"fdsd"
}
]
C Class Component
import React from 'react'
import data from './data.json'
import { useHistory } from 'react-router'
function C() {
let history = useHistory();
function handleClick() {
history.push("/payment");
}
return (
<div >
{data.map((postData) =>{
console.log(postData)
return(
<div key=
{postData.id}>
<div className='absolute '>
<button onClick={handleClick}className=' absolute text-black-600 h-10 ml-24 mt-32 bg-white w-
36 rounded-full focus:outline-none focus:ring-2 focus:ring-gray-600'>Buy Now</button>
<img className='w-screen object-contain'src={postData.imgC}></img>
<h1 className='absolute ml-24 md:text-5xl sm:text-5xl top-8'>{postData.classC}</h1>
<h1 className='text-base font-mono absolute ml-24 top-24'>{postData.priceC}</h1>
</div>
</div>
)
})
}
</div>
)
}
export default C
App Component
import React,{useState, useEffect} from 'react'
import './assets/main.css'
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
import Header from './Header'
import Home from './Home'
import A from './Models/A'
import B from './Models/B'
import C from './Models/C'
import Payment from './Payment';
function App() {
return (
<div >
<div >
<Router>
<Header />
<Switch>
<Route path="/payment">
<Payment/>
</Route>
<Route path="/C">
<C/>
</Route>
<Route path="/B">
<B />
</Route>
<Route path="/A">
<A />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</Router>
</div>
</div>
);
}
export default App;
Home Component
import React from 'react'
import {
BrowserRouter as Router,
NavLink
} from "react-router-dom";
function Home() {
return (
<div className='ml-20'>
<nav className='bg-red-50 max-w-full'>
<ul >
<li>
<Link to="/A">A-Class</Link>
</li>
<li>
<Link to="/B">B-Class</Link>
</li>
<li>
<Link to="/C">C-Class</Link>
</li>
</ul>
</nav>
</div>
)
}
export default Home

You should probably change your route to one with a parameter
<Route path="/payment/:dataId" component={Payment}></Route>
and convert the button to a Link which also passes the id
<Link
to={`/payment/${postData.id}`}
and in the Payment component
also include access to the data.json
get the url parameter from the props
use the provided parameter to find the relevant item in the data
Something like this: https://codesandbox.io/s/festive-spence-bw18s?file=/src/App.js

You can pass additional data with history.push and get it from props in Payment page.
In your C component:
import React from 'react'
import data from './data.json'
import { useHistory } from 'react-router'
function C() {
let history = useHistory();
function handleClick(postData) {
// Pass additional data to Payment component when changing route.
history.push({
pathname: '/payment',
state: {
price: postData.price,
image: postData.image,
class: postData.class
}
});
}
return (
<div >
{data.map((postData) => {
console.log(postData)
return (
<div key=
{postData.id}>
<div className='absolute '>
{/** pass postData to handleClick function */}
<button onClick={() => handleClick(postData)} className=' absolute text-black-600 h-10 ml-24 mt-32 bg-white w-
36 rounded-full focus:outline-none focus:ring-2 focus:ring-gray-600'>Buy Now</button>
<img className='w-screen object-contain' src={postData.imgC}></img>
<h1 className='absolute ml-24 md:text-5xl sm:text-5xl top-8'>{postData.classC}</h1>
<h1 className='text-base font-mono absolute ml-24 top-24'>{postData.priceC}</h1>
</div>
</div>
)
})
}
</div>
)
}
export default C
Inside your Payment component you can pull the price, image and class out this way:
import React from 'react';
import { useLocation } from "react-router-dom";
const Payment = () => {
// ...
const location = useLocation();
console.log(location.state.image) // image url from C
console.log(location.state.class) // class from C
console.log(location.state.price) // price from C
// ...
}
export default Payment;

Related

pass in props into component to render

// Warning: Cannot read properties of undefined (reading 'params')
// im try to get movie_id from movielist.js to view single movie on movie.js onclicking view review
// basically my error is from inability to pass the props into movie.js
//in nav/index.js
import { BrowserRouter as Router, Routes, Route, useParams} from "react-router-dom";
import Navbar from './navbar';
import MovieList from "../components/movie-list"
import Movie from "../components/movie"
const Nav = () => {
return (
<Router>
<Navbar/>
<Routes>
<Route exact path={'/'} element={<MovieList/>}/>
<Route path='/movies/:id/' element={<Movie props={useParams()} />} />
</Routes>
</Router>
)}
//in movielist.js
import React, {useState, useEffect} from 'react'
import MovieDataService from "../services/movie"
import { Link } from 'react-router-dom'
const MovieList = () => {
....
return (
<div>
....
<div>
{movies.map((movie)=>{
return(
<div className="card" key={movie._id}>
<div className="card-container">
<div className='card-img'>
<img src={movie.poster+"/100px180"} alt=""/>
</div>
<div className="card-body">
<h1>{movie.title}</h1>
<h2>Rating:{movie.rated}</h2>
<p>{movie.plot}</p>
<Link to={"/movies/"+movie._id}>View Review</Link>
</div>
</div>
</div>
);
})}
</div>
</div>
)
}
// in movie.js
import React, { useState, useEffect } from 'react'
import MovieDataService from '../services/movie'
import { Link } from 'react-router-dom'
const Movie = (props) => {
useEffect(()=>{
getMovie(props.match.params.id)
},[props.match.params.id]) //won't call getMovie Multiple times unless id is updated.
return (
<div>
<div className="card-container">
<div className='card-img'>
<img src={movie.poster+"/100px250"} alt=""/>
</div>
<div className="card-body">
<h1>{movie.title}</h1>
<p>{movie.plot}</p>
{props.user && <Link to={"/movies/"+props.match.params.id+"/review"}>Add Review</Link>
}
</div>
</div>
);
})}
</div>
</div>
)
}
Use useParams() hook to get url params.
const {id} = useParams()
useEffect(()=>{
getMovie(id)
},[id])
replace props.match.params.id with id everywhere

Am Unable to pass the value from Child to Parent component(FUNCTIONAL COMPONENT) in ReactJS

am trying to build an E-Commerce website with ReactJS(Without any backend or server).
Totally I have 4 components:
Navbar.jsx
Home.jsx
Products.jsx
Cart.jsx
**what i want is, when user clicks on ADD TO CART button in products.jsx, cart number should be displayed on Navbar top right corner but its not displaying.
what i tryed: i just passed props from Products.jsx page to Navbar.jsx but its not working. i tried lot but am unable to do it.. please help me...Thanks in Advance
[am familiar with functional components only]**
CODE : Navbar.jsx
import React from 'react'
import { Link } from 'react-router-dom'
function Navbar(props) {
return (
<div>
<div className="d-flex bg-primary flex-row justify-content-between text-light ">
<div className="left d-flex">
<li className="my-2"><Link className="text-light p-3 py-2" to="/">HOME</Link></li>
<li className="my-2"><Link className="text-light p-3 py-2" to="/products">PRODUCTS</Link></li>
<li className="my-2"><Link className="text-light p-3 py-2" to="/cart">CART</Link></li>
</div>
<div className="right">
<p>CART is:</p><p className="mx-2 h3">{props.text}</p>
{/* I WANT TO DISPLAY THE CART ABOVE HERE */}
</div>
</div>
</div>
)
}
export default Navbar
CODE : Products.jsx
import React, { useState } from 'react'
import Router from '../Router';
import Navbar from './Navbar';
function Products() {
return (
<div>
<h1>PRODUCTS</h1>
<button className="btn btn-success">ADD TO CART</button>
{/* WHEN I CLICK ON ADD TO CART, CART NUMBER SHOULD UPDATED IN NAVBAR */}
</div>
)
}
export default Products
CODE : Router.jsx
import React from 'react'
import {
BrowserRouter,
Switch,
Route,
Link
} from "react-router-dom";
import Home from './components/Home';
import Navbar from './components/Navbar';
import Products from './components/Products';
import Cart from './components/Cart';
function router() {
return (
<>
<BrowserRouter>
{/* <Navbar text="3"/> */}
<Navbar/>
<Switch>
<Route exact path='/' component={Home}/>
<Route exact path='/cart' component={Cart}/>
<Route exact path="/products" component={Products}/>
</Switch>
</BrowserRouter>
</>
)
}
export default router
CODE : index.js
import React from 'react';
import ReactDOM from 'react-dom';
import Home from './components/Home';
import Navbar from './components/Navbar';
import Products from './components/Products';
import './index.css';
import {
BrowserRouter,
Switch,
Route,
Link
} from "react-router-dom";
import Router from './Router';
ReactDOM.render(
<Router />
,
document.getElementById('root')
);
FOLDER STRUCTURE:
folder structure
PLEASE HELP ME...THANKS IN ADVANCE
In Router.jsx, you need to have a state to store cart number
pass this state value as a prop to Navbar.jsx, when this state update, Navbar prop would be update, too
pass setState callback as a prop to Products.jsx, when click "Add To Cart", call this callback, then state value will be updated
Router.jsx
import React, { useState } from "react";
import { BrowserRouter, Switch, Route, Link } from "react-router-dom";
import Home from "./components/Home";
import Navbar from "./components/Navbar";
import Products from "./components/Products";
import Cart from "./components/Cart";
function Router() {
// a state to store cart number
const [text, setText] = useState(3);
return (
<>
<BrowserRouter>
<!-- pass state value as a prop to Navbar -->
<Navbar text={text} />
{/* <Navbar /> */}
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/cart" component={Cart} />
<!-- pass setText callback as a prop to Products -->
<Route
exact
path="/products"
component={() => <Products setText={setText} />}
/>
</Switch>
</BrowserRouter>
</>
);
}
export default Router;
Products.jsx
import React, { useState } from "react";
import Router from "../Router";
import Navbar from "./Navbar";
function Products(props) {
const { setText } = props;
return (
<div>
<h1>PRODUCTS</h1>
<!-- when button click, call setText to update text state -->
<button
className="btn btn-success"
onClick={() => {
setText((prev) => prev + 1);
}}
>
ADD TO CART
</button>
{/* WHEN I CLICK ON ADD TO CART, CART NUMBER SHOULD UPDATED IN NAVBAR */}
</div>
);
}
export default Products;
What you must do is transfer the value to display in the cart from the Products page to the navbar, on button click.
Both Navbar and Products components have a shared parent; Router.jsx. This means your value has to go from Navbar.jsx, up to a state in Router.jsx via a "callback". The state will then be given as the prop to the Navbar.
Following that approach will allow you to dynamically update. To summize; All you need is 1 state in Router, and 1 callback as prob in Navbar, which updates the state in Router.

Having trouble filtering the data from json

Hello again Stackoverflow members.I have GLS Component I have more similiar components to GLS concept is the same but styling is not, anyway the thing I want to achieve is this, when I press on the Link in GLS/A Component I want to display/Render the image class and price of that Component on the payment page for some reason it is giving me this error 'TypeError: Cannot read property 'image' of undefined'. I would be very grateful if someone could help me.
Gls Component
import React from "react";
import data from "../data.json";
import { Link } from "react-router-dom";
function GLS({product}) {
return (
<div>
<div key={product.id} className="m-4 bg-blue-100 rounded-xl p-8 absolute ">
<div>
<Link
to={`/payment/${product.id}`}
className="py-1 px-2 text-black-600 h-10 ml-24 mt-32 bg-white w-
36 rounded-full focus:outline-none focus:ring-2 focus:ring-gray-600"
>
Buy Now
</Link>
<img
alt=""
className="w-screen object-contain"
src={product.image}
></img>
<h1 className=" ml-24 md:text-5xl sm:text-5xl top-8">
{product.class}
</h1>
<h1 className="text-base font-mono ml-24 top-24">
{product.price}
</h1>
</div>
</div>
</div>
);
}
export default GLS;
App Component
import React,{useState, useEffect} from 'react'
import './assets/main.css'
import A from './Models/GLS Model/A'
import GLS from './Models/GLS Model/GLS'
import data from "./Models/data.json";
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
return (
<div className='' >
<div >
<Router>
<Switch>
<Route path="gls">
{data.map((product) => (
<GLS key={product.id} product={product} />
))}
</Route>
<Route path="a">
{data.map((product) => (
<A key={product.id} product={product} />
))}
</Route>
<Route path="/payment/:productId">
<Payment />
</Route>
<Route exact path="/">
<Home />
</Route>
</Switch>
</Router>
</div>
</div>
);
}
export default App;
import React from 'react'
import {
Link,
} from "react-router-dom";
import data from "./Models/data.json";
function Home() {
return (
<div className='ml-20'>
<nav className='bg-red-50 max-w-full'>
<ul >
<li>
<Link to='/gls'>GLS-class</Link>
</li>
<li>
<Link to="/a"> A-Class</Link>
</li>
</ul>
</nav>
</div>
)
}
export default Home
Payment Component
import React from "react";
import { useParams } from "react-router-dom";
import data from "./Models/data.json";
const Payment = () => {
const { productId } = useParams();
const filteredData = data.filter((product) => product.id === productId)[0];
return (
<div className="ml-20">
<img alt="" className="w:2/4 object-contain " src={filteredData.image} />
<h2
className=" ml-24 mlg:ml-6 mlg:mt-2 mlg:static text-5xl mlg:text-2xl text-blue-400 absolute top-
48"
>
{filteredData.class}
</h2>
<h3
className="text-lg mlg:mb-2 mlg:ml-6 mlg:mt-2 mlg:static font-bold text-green-800
font-mono ml-24 top-64 absolute"
>
{filteredData.price}
</h3>
</div>
);
};
export default Payment;
Json file
[
{
"id": 0,
"class": "A-Class",
"image": "./ModImages/Aclass.jpg",
"price": "It goes around $37,300",
},
{
"id": 1,
"class": "GLS-Class",
"image": "./ModImages/GLSclass.jpg",
"price": "It goes around $47,700"
}
]
TypeError: Cannot read property 'image' of undefinedThis is a great error to have because it more or less tells you exactly what's wrong. In basic terms, undefined means that a variable has been declared but has not yet been assigned a value.
function myFunc(product) {
return product.img;
}
var product; //initialized to undefined, must explicitly set type;
console.log(myFunc(product));
Result -> Uncaught TypeError: product is undefined
function myFunc(product) {
return product.img;
};
var product; //undefined
product = {}; //explicitly setting to object
product.img = 'image'; // set a name and value
console.log(myFunc(product));

How can I use nested routes with props for a child component

I'm building an react app where I have a feed component and the feed component consists of array of post components. The post component contains a link in it for viewing the full post component. I'm not able to pass the respective props to the full post component. I'm not able to do a nested route for the fullpost component.
this is my layout component
import React, { Component } from "react";
import Header from "../Header/Header";
import classes from "./Layout.css";
import { Route, Switch } from "react-router-dom";
import FullPost from "../Feed/FullPost/FullPost";
import axios from "axios";
import Feed from "../Feed/Feed";
class Layout extends Component {
state = {
users: [],
};
componentDidMount() {
axios
.get("https://goodwill-60d8a.firebaseio.com/Users.json")
.then((response) => {
this.setState({ users: response.data });
});
}
render() {
console.log(this.state.users);
return (
<div className={classes.main}>
<div>
<Header />
</div>
<div className={classes.content}>
<Switch>
<Route
path="/"
exact
render={() => <Feed users={this.state.users} />}
/>
<Route path="/fullpost" exact render={() => <FullPost />} />
</Switch>
</div>
</div>
);
}
}
export default Layout;
FEED component
import React from "react";
import Post from "./Post/Post";
import classes from "./Feed.css";
const feed = (props) => {
const feedItems = Object.keys(props.users).map((key) => ({
id: key,
...props.users[key],
}));
return (
<div className={classes.feed}>
{feedItems.map((items) => (
<Post
key={items.id}
profilename={items.profileName}
profilepic={items.profilePic}
timestamp={items.timeStamp}
contentimage={items.contentImage}
contenttext={items.contentText}
trend={items.trend}
></Post>
))}
</div>
);
};
export default feed;
Post component
import React from "react";
import classes from "./Post.css";
import ShareButton from "../../UI/ShareButton/ShareButton";
import { Link } from "react-router-dom";
const post = (props) => {
return (
<div className={classes.post}>
<div className={classes.header}>
<div className={classes.profileimage}>
<img className={classes.pic} src={props.profilepic} alt="" />
</div>
<div className={classes.name}>{props.profilename}</div>
<div className={classes.timestamp}>{props.timestamp}</div>
</div>
<div className={classes.container}>
<div className={classes.image}>
<img src={props.contentimage} alt="" />
</div>
<div>
<div className={classes.text}>
<span>{props.contenttext}</span>
</div>
<div className={classes.fullpost}>
<Link to="/fullpost" {...props}>
See Full Post
</Link>
</div>
</div>
</div>
<div className={classes.footer}>
<div className={classes.trend}>
<span>{props.trend}</span>
</div>
<ShareButton />
</div>
</div>
);
};
export default post;
Full Post component
import React from "react";
import classes from "./FullPost.css";
import pic from "../../../Assets/Images/self.jpg";
import { Link } from "react-router-dom";
const fullPost = (props) => {
return (
<div className={classes.fullpost_container}>
<div className={classes.photo_container}>
<img src={props.profilepic} alt=" " />
</div>
<div className={classes.sidebar}>
<div className={classes.profileimage}>
<img src={props.profilePic} alt="" />
</div>
<div className={classes.profilename}>Tony Kroos</div>
<div className={classes.timestamp}>3 Hours Ago</div>
</div>
<div className={classes.feedlink}>
<Link to="/" className={classes.feedlink_text}>
See more posts
</Link>
</div>
</div>
);
};
export default fullPost;

React Router v4 not loading component

For some reason, my web app is not directing to the component whenever I go to the parameters. Specifically, it is not going to the Battle component.
Here is what the navigation looks:
import React from 'react';
import Header from './components/Header/Header';
import SelectPlayers from './pages/SelectPlayers/SelectPlayers';
import Popular from './pages/Popular/Popular'
import Battle from './pages/Battle/Battle'
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
function App() {
return (
<Router>
<div className={'flex flex-column'}>
<Header />
<Switch>
<Route exact path={'/'} component={Popular}/>
<Route exact path={'/battle/select-player'} component={SelectPlayers} />
<Route exact path={'/results?playerOne=:playerOne&playerTwo=:playerTwo'} component={Battle} />
</Switch>
</div>
</Router>
);
}
export default App;
In the SelectPlayers component, whenever the user presses a button it runs:
import React, {useState} from 'react';
function SelectPlayers(props) {
const [playerOne, setPlayerOne] = useState('');
const [playerTwo, setPlayerTwo] = useState('');
function setPlayerName(event, player){
if (player === 1){
setPlayerOne(event.target.value)
} else if (player === 2) {
setPlayerTwo(event.target.value)
}
}
function goToBattle(event){
event.preventDefault();
props.history.push(`/results?playerOne=${playerOne}&playerTwo=${playerTwo}`)
}
return (
<div className={'pa3 mh7-l mh7-m'}>
<div className="flex flex-column">
<div className={'mb1'}>
<h1 className={'mb0'}>Player One</h1>
<input onChange={(e) => setPlayerName(e, 1)} type="text" placeholder={'github username'} className={'input-reset pa1 w-100 h2 ba b--black br2'}/>
</div>
<div className="tc dark-red">
<h1>Versus</h1>
</div>
<div className={'mb3'}>
<h1 className={'mb0 mt0 tr'}>Player Two</h1>
<input onChange={(e) => setPlayerName(e, 2)} type="text" placeholder={'github username'} className={'input-reset pa1 w-100 h2 ba b--black br2'}/>
</div>
<div>
<button onClick={(e) => goToBattle(e)} className={'input-reset pa1 h2 fw1 bg-black white ba w-100 b--black br2'}>Battle</button>
</div>
</div>
</div>
);
}
export default SelectPlayers;
On the Battle component, I write some console.log stuff just to check if the Component loaded. However, whenever I go to that parameter, none of the code in my componentDidMount is running. I don't see any of the console.logs I wrote in componentDidMount in my developer console. Here is the component:
import React, {Component} from 'react';
class Battle extends Component {
constructor(props){
super(props)
}
componentDidMount() {
console.log('runngins');
console.log(this.props);
}
render() {
return (
<div className={'pa3 mh7-l mh7-m'}>
<div className="flex flex-column">
</div>
</div>
);
}
}
export default Battle;
You can see the code at this repo: https://github.com/tarekgabarin/github_compete
It would be greatly appreciated if anyone helped me.
As per your new comment that code is working without queryset, looks like there is some problem with your queryset parameters.
As suggested in comment box, don't define Router with queryset.
<Switch>
<Route exact path={'/'} component={Popular}/>
<Route exact path={'/battle/select-player'} component={SelectPlayers} />
<Route exact path={'/results'} component={Battle} />
</Switch>
In your SelectPlayers component, navigate to next page with queryset.
props.history.push("/results?playerOne=" +playerOne+ "&playerTwo=" +playerTwo)
On Battle component, use (query-string) to read the parameter. For example:
const values = queryString.parse(this.props.location.search);
const player_one = values.playerOne
const player_two = values.playerTwo
Please note that my above code is not tested.
Thanks

Categories