Specific page route in ReactJS via JSON Id - json

I want to route to a specific page and show a specific JSON Object. If JSON Object contains ID: 1 then it should go to localhost:300/users/1 and show the data of Id 1. I have also mapped another JSON which contains addresses of users and this is I have done so far.
User.jsx
import React from "react";
import users from "../data/PersonData.json";
import adresses from "../data/StreetAddress.json";
class Users extends React.Component {
constructor(props) {
super(props);
this.state = {
Users: []
};
}
render() {
const result = {
Users: users.User.map(user => ({
...user,
adresses: adresses.StreetAddress.filter(
adr => adr.PersonId === user.Id
).map(({ PersonId, ...rest }) => rest)
}))
};
return <div id="users"> {JSON.stringify(result)} </div>;
}
}
export default Users;
and it results into whole JSON Object mapped with address, How can I route it to specific ID i.e. Id which is in
PersonData.json
{
"User": [
{
"BossId": 3,
"DateOfBirth": "1966-09-27T00:00:00",
"FamilyName": "Montejano",
"Gender": "Unspecified",
"GivenName": "Trinh",
"Id": 8,
"Title": "Tech Manager"
},
]
}
So when a user is routed to localhost:3000/users/8 it should show only specific data of user 8.

I solved this in the following way, I took the URL Parameters and got the ID from there and matched it with JSON Object which is looping.
In App.js
import React from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import Users from "./Components/Users";
import User from "./Components/User";
class App extends React.Component {
render() {
return (
<div className="App">
<Router>
<>
<Switch>
<Route path="/users" name="users" component={Users} />
<Route path="/user/:id" name="user" component={User} />
</Switch>
</>
</Router>
</div>
);
}
}
export default App;
and in User.jsx
import React from "react";
import users from "../data/PersonData.json";
import adresses from "../data/StreetAddress.json";
class User extends React.Component {
constructor(props) {
super(props);
this.state = {
Users: []
};
}
render() {
const result = {
Users: users.User.map(user => ({
...user,
adresses: adresses.StreetAddress.filter(
adr => adr.PersonId === user.Id
).map(({ PersonId, ...rest }) => rest)
}))
};
const params = this.props.match.params.id;
return JSON.stringify(result.Users[params]);
}
}
export default User;
I have reused the same code in the question.

Related

Passing props in react - fetching

I'm simply trying to pass props through components and render it in jsx but somehow that wouldn't work. I was searching for the problem but just cannot find it.
I'm trying pass props from this component:
import React from "react";
import "../styles/Products.css";
import ProductItem from "../items/ProductItem";
class Products extends React.Component {
constructor(props) {
super(props);
this.state = {
data: []
};
}
componentDidMount() {
fetch("../products.json")
.then(response => response.json())
.then(response => this.setState({ data: response.products }));
}
render() {
return (
<div className="products-container">
<ProductItem data={this.state.data[0]} />
</div>
);
}
}
export default Products;
to this component:
import React from "react";
import "../styles/ProductItem.css";
const ProductItem = props => {
console.log(props.data, "current");
return (
<div className="product-item">
<img src="" alt="" className="bike-image" />
<div className="active-product" />
<div className="view-details">Compare</div>
<h2>Bike</h2>
<h4>downhill bike</h4>
<p>3500 PLN</p>
</div>
);
};
export default ProductItem;
And the problem is when I'm looking in my react dev tools, props has passed properly, but when I'm trying to get to attributes of the object like props.data.id, I get an error:
Cannot read property 'id' of undefined
fetch needs some time to get the response and populate the this.state.data array. So you need to check if the this.state.data[0] value is really available or not. You can try this-
render() {
return (
<div className="products-container">
{this.state.data && this.state.data.length > 0 && <ProductItem data={this.state.data[0]} />}
</div>
);
}

How to create dynamic routes with react-router-dom?

I learn react and know, how to create static routes, but can't figure out with dynamic ones. Maybe someone can explain, I'll be very grateful. Let there be two components, one for rendering routes, and another as a template of a route. Maybe something wrong in the code, but hope You understand..
Here is the component to render routes:
import React, { Component } from 'react';
import axios from 'axios';
import Hero from './Hero';
class Heroes extends Component {
constructor(props) {
super(props);
this.state = {
heroes: [],
loading: true,
error: false,
};
}
componentDidMount() {
axios.get('http://localhost:5555/heroes')
.then(res => {
const heroes = res.data;
this.setState({ heroes, loading: false });
})
.catch(err => { // log request error and prevent access to undefined state
this.setState({ loading: false, error: true });
console.error(err);
})
}
render() {
if (this.state.loading) {
return (
<div>
<p> Loading... </p>
</div>
)
}
if (this.state.error || !this.state.heroes) {
return (
<div>
<p> An error occured </p>
</div>
)
}
return (
<div>
<BrowserRouter>
//what should be here?
</BrowserRouter>
</div>
);
}
}
export default Heroes;
The requested JSON looks like this:
const heroes = [
{
"id": 0,
"name": "John Smith",
"speciality": "Wizard"
},
{
"id": 1,
"name": "Crag Hack",
"speciality": "Viking"
},
{
"id": 2,
"name": "Silvio",
"speciality": "Warrior"
}
];
The route component (maybe there should be props, but how to do it in the right way):
import React, { Component } from 'react';
class Hero extends Component {
render() {
return (
<div>
//what should be here?
</div>
);
}
}
export default Hero;
I need something like this in browser, and every route url should be differentiaie by it's id (heroes/1, heroes/2 ...):
John Smith
Crag Hack
Silvio
Each of them:
John Smith.
Wizard.
and so on...
Many thanks for any help!)
Use Link to dynamically generate a list of routes.
Use : to indicate url params, :id in the case
Use the match object passed as props to the rendered route component to access the url params. this.props.match.params.id
<BrowserRouter>
/* Links */
{heroes.map(hero => (<Link to={'heroes/' + hero.id} />)}
/* Component */
<Route path="heroes/:id" component={Hero} />
</BrowserRouter>
class Hero extends Component {
render() {
return (
<div>
{this.props.match.params.id}
</div>
);
}
}
Update so this works for React Router v6:
React Router v6 brought some changes to the general syntax:
Before: <Route path="heroes/:id" component={Hero} />
Now: <Route path="heroes/:id" element={<Hero />} />
You can't access params like with this.props.match anymore:
Before: this.props.match.params.id
Now: import {useParams} from "react-router-dom";
const {id} = useParams();
You can now just use id as any other variable.
To do this you simply add a colon before the url part that should be dynamic. Example:
<BrowserRouter>
{/* Dynamic Component */}
<Route path="heroes/:id" component={Hero} />
</BrowserRouter>
Also you can use the useParams hook from react-router-dom to get the dynamic value for use in the page created dynamically. Example:
import { useParams } from "react-router-dom";
const Hero = () => {
const params = useParams();
// params.id => dynamic value defined as id in route
// e.g '/heroes/1234' -> params.id equals 1234
return (...)
}

Access values from json in react

I am trying to access variables from json in react component.
This is JSON I am getting:
{
"id": 5,
"title": "Hello",
"text": "Hello, this is my first article...",
"picture": "pic",
"comments": [],
"user": {
"id": 3,
"name": "Anonim",
"password": "123456"
}
}
The attached user is person who created the post.
The attached comments is list of comments related to this post.
In routing I am doing the following:
<Switch>
<Route path='/' exact component={PostsPage} />
<Route path='/:id' exact component={PostProfilePage} />
</Switch>
In react class component
class PostProfile extends Component {
constructor(props){
// Pass props to the parent component
super(props);
// Set initial state
this.state = {
// State needed
post: []
};
}
componentDidMount() {
this.fetchPost();
}
fetchPost() {
const {match} = this.props
const id = match.params.id
console.log(id)
fetch('/'+id)
.then(res => {
return res.json();
})
.then(data => {
this.setState({
post: data
});
})
.catch(err => {
console.log(err);
});
}
render() {
return (
<div>
<li> {this.state.post.title} </li>
<li> {this.state.post.text} </li>
</div>
)
}
}
export default withRouter(PostProfile)
does not work
<li> {this.state.post.user.name} </li>
<li> {this.state.post.comments...} </li>
Why I cannot access user and comments?
And is it possible to get user and comments in different components? (not calling the fetch method again and again)?
Thank you in advance!
Your post at first time has no data, so you need something like:
import React, { Component } from 'react';
export default class Test extends Component {
constructor(props) {
// Pass props to the parent component
super(props);
// Set initial state
this.state = {
// State needed
post: []
};
}
componentDidMount() {
this.fetchPost();
}
fetchPost() {
fetch('https://swapi.co/api/people/1')
.then(res => {
return res.json();
})
.then(data => {
this.setState({
post: data
});
})
.catch(err => {
console.log(err);
});
}
render() {
const show = this.state.post.length === 0 ?
<h1> ...loading </h1>
: <h1> {this.state.post.birth_year} </h1>
return (
<div>
<h1> { show } </h1>
</div>
)
}
}

Parser data with format json in react

I am new to react.js and I am trying to display data in JSON format in a table. So what I did is:
import React from 'react';
import axios from 'axios';
class TableUser extends React.Component {
constructor(props) {
super(props);
this.state = {
libelle_produit: ''
};
}
componentDidMount(){
axios
.get('admin/prdtId/')
.then(({ data })=> {
this.setState({
libelle_produit: data.libelle_produit
});
})
.catch((err)=> {})
}
render() {
return <div>
<p>{ this.state.libelle_produit }</p>
</div>;
}
}
export default TableUser;
i'd want to be able to access the libelle product of each component and print those on the website
[{"libelle_produit":"test produit"}]
Thanks
<div>
{ this.state.libelle_produit != '' ? this.state.libelle_produit.map( (item, index) =>
<p>{libelle_produit</p>
}
</div>
If the array isnt empty, then loop trough the array and return a p tag with the title of the libelle_produit

In React.js array value is not passing properly via props?

I have a react app that has two components one Customer and another called Tags. The Customer sends its state's tags value to Tags. As following:
Customer.jsx
import React from "react";
import Tags from "./Tags.jsx";
export default class Customer extends React.Component {
constructor(props) {
super(props);
this.state = {customer:''};
}
componentDidMount(){
const url = `http://localhost:3000/api/customers/${this.props.params.id}`
fetch(url)
.then(res=>res.json())
.then(data=>{
console.log(data);
this.setState({
customer: data
});
})
.catch(error=>{
console.log(error)
});
}
render() {
return (
<div>
Company Name :{this.state.customer.companyName}
Customer Name :{this.state.customer.name}
Tags: <Tags tags={this.state.customer.tags} />
</div>
);
}
}
Tags.jsx
import React from "react";
export default class Tags extends React.Component {
constructor(props) {
super(props);
}
render() {
let tags = this.props.tags.map(tag=>{
return (<span>tag</span>);
});
return (
<div>
{tags}
</div>
);
}
}
When I run the code I get, "TypeError: Cannot read property 'map' of undefined(…)". If I replace below from Tags.jsx
let tags = this.props.tags.map(tag=>{
return (<span>tag</span>);
});
with
console.log(this.props.tags);
The output is an array.
What is happening? I really do not understand. What can I do?
In the constructor of Customer you are defining the state of a customer as a string, not an object. You should change it to reflect the actual customer properties, ie:
this.state = {customer: {name: '', tags: []}};
It's undefined, because of you're making an API call and the data isn't returned yet.
In your Customer component you can check the existance of this.state.customer.tags and if exist - then render the tags.
Somethling like that:
{ this.state.customer.tags ? <Tags tags={this.state.customer.tags} /> : null }