How can I pass props to another components with in reactjs - reactjs

I'm trying to pass product data from AllProducts component to Product component.
AllProducts.jsx: is showing all the products I have and Product.jsx will show specific product and how can I pass data to Product.jsx?
Here is my AllProducts.jsx:
const AllProducts = (props) => {
const [products, setProducts] = useState([]);
const getProductsAPI = () => {
axios
.get("http://localhost:8000/api/products")
.then((res) => {
setProducts(res.data);
getProductsAPI();
})
.catch((err) => {
console.log(err);
});
};
useEffect(() => {
getProductsAPI();
}, [props]);
return (
<div>
<table className="table table-bordered table-hover">
<thead>
<tr>
<th>#</th>
<th>Title</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{products.map((product, i) => (
<tr key={i}>
<th scope="row">{i}</th>
<td>{product.title}</td>
<td>
<Link to={`/products/${product._id}`}> View </Link>
</td>
</tr>
))}
</tbody>
</table>
</div>
);
};
and here is my Product.jsx:
const Product = (props) => {
return (
<div className="container">
<h4>{props.product.title}</h4>
</div>
);
};
export default Product;
Here is my project github if you want to look at all the code I have: https://github.com/nathannewyen/full-mern/tree/master/product-manager

If the data is fully loaded for each product in AllProducts, and you don't want to make another API call by product id in the Product component, in this case, you don't have to use a route link to view Product, just make a conditional rendering to show Product component inside AllProducts component. pseudo-code as below,
const [showProduct, setShowProduct] = useState(false);
const [currentProduct, setCurrentProduct] = useState();
const showProduct = (product) => {
setShowProduct(true);
setCurrentProduct(product);
}
<tbody>
{products.map((product, i) => (
<tr key={i}>
<th scope="row">{i}</th>
<td>{product.title}</td>
<td>
<button type="button" onclick = {showProduct(product)}>View</button>
</td>
</tr>
))}
</tbody>
return (showProduct ? <Product /> : <AllProucts/>)
If you also need to make another API call to get extra data for each product, then use the router link but perhaps you can not pass props.

Related

fetching data not showing in table in react

I am create a table and fetching data using axios but in the table I am not able to print the data when I check data is printing in browser but not able to print the particular data to a table format so what should be change in my code?
import { useEffect, useState } from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import { Table } from "react-bootstrap";
import axios from "axios";
export default function App() {
const [user, setUser] = useState([]);
useEffect(() => {
axios
.get("https://jsonplaceholder.typicode.com/users", (req, res) => {
res.json();
})
.then((data) => setUser({ ...user, data }))
.catch((error) => console.error(error));
});
return (
<div className="App">
<h3 className="text-primary">User List</h3>
<Table
variant="danger"
striped
bordered
hover
className="shadow-lg text-center"
>
<thead>
<tr>
<th>id</th>
<th>Name</th>
<th>UserName</th>
<th>Email</th>
</tr>
</thead>
<tbody>
{user?.data?.length > 0 &&
user.data.map((user) => {
return (
<tr key={user.id}>
<td>{JSON.stringify(user.data["data"].id)}</td>
<td>{JSON.stringify(user.data["data"].name)}</td>
<td>{JSON.stringify(user.data["data"].username)}</td>
<td>{JSON.stringify(user.data["data"].email)}</td>
</tr>
);
})}
</tbody>
</Table>
{/* <div>{JSON.stringify(user.data["data"])}</div> */}
</div>
);
}
for example
import { useEffect, useState } from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import { Table } from "react-bootstrap";
import axios from "axios";
export default function App() {
const [user, setUser] = useState([]);
useEffect(() => {
axios
.get("https://jsonplaceholder.typicode.com/users")
.then((res) => {
setUser(res.data);
})
.catch((error) => console.error(error));
}, []);
return (
<div className="App">
<h3 className="text-primary">User List</h3>
<Table
variant="danger"
striped
bordered
hover
className="shadow-lg text-center"
>
<thead>
<tr>
<th>id</th>
<th>Name</th>
<th>UserName</th>
<th>Email</th>
</tr>
</thead>
<tbody>
{user?.length > 0 &&
user.map((userData) => {
return (
<tr key={userData.id}>
<td>{userData.id}</td>
<td>{userData.name}</td>
<td>{userData.username}</td>
<td>{userData.email}</td>
</tr>
);
})}
</tbody>
</Table>
{/* <div>{JSON.stringify(user)}</div> */}
</div>
);
}
Replace the useEffect code as follow.
useEffect(() => {
axios
.get("https://jsonplaceholder.typicode.com/users")
.then((data) => setUser({ ...user, data }))
.catch((error) => console.error(error));
}, []);
You already know that calling this api will give you an array of users so you can initialise the state as empty array as:
const [users, setUsers] = useState([]);
and when you are using axios then you don't have to use res.json(). axios will do it for you out of the box.
axios
.get("https://jsonplaceholder.typicode.com/users")
.then(({ data }) => setUsers(data))
.catch((error) => console.error(error));
so, after getting data using get method of axios it will return you a promise and you can get data from its data property that is passed an first args. You can directly set state which will be an array of objects.
.then(({ data }) => setUsers(data))
Here I've destructed the object to get only the data property.
Since users will be an array of objects, so you don't have to do any check. You can directly use user.id to get the respective property.
Codesandbox link
export default function App() {
const [users, setUsers] = useState([]);
useEffect(() => {
axios
.get("https://jsonplaceholder.typicode.com/users")
.then(({ data }) => setUsers(data))
.catch((error) => console.error(error));
}, []);
return (
<div className="App">
<h3 className="text-primary">User List</h3>
<Table
variant="danger"
striped
bordered
hover
className="shadow-lg text-center"
>
<thead>
<tr>
<th>id</th>
<th>Name</th>
<th>UserName</th>
<th>Email</th>
</tr>
</thead>
<tbody>
{users.map((user) => {
return (
<tr key={user.id}>
<td>{user.id}</td>
<td>{user.name}</td>
<td>{user.username}</td>
<td>{user.email}</td>
</tr>
);
})}
</tbody>
</Table>
{/* <div>{JSON.stringify(user.data["data"])}</div> */}
</div>
);
}

TypeError: data.map is not a function i am getting an error while api call and an error called id is not defined

i want to navigate to other page while clicking on the button and while clicking the button i also have to call an api.but its not working can anyone tell me whats the problem
[its the api link] [1]: https://api.tvmaze.com/shows/$%7Bid%7D its my contact component
import React,{useState,useEffect} from 'react';
import axios from 'axios';
export const Contact = () => {
const url = `https://api.tvmaze.com/shows/${id}`;
const [data, setData] = useState([]);
useEffect(() => {
axios.get(url).then((json) => setData(json.data));
}, []);
const renderTable = () => {
return data.map((user, i) => {
return (
<tr key={i}>
<td>{user.show?.name}</td>
<td>{user.show?.language}</td>
<td>{user.show?.genres}</td>
<td>{user.show?.runtime}</td>
<td>{user.show?.premiered}</td>
<td>{user.show?.rating?.average}</td>
<td>{user.show?.network?.country?.name}</td>
<td>
<img src={user?.show?.image?.medium} alt="poster" />
</td>
</tr>
);
});
};
return (
<div>
<table className=" table table-bordered">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">language</th>
<th scope="col">genres</th>
<th scope="col">runtime</th>
<th scope="col">premiered</th>
<th scope="col">Rating</th>
<th scope="col">country name</th>
<th scope="col">image</th>
</tr>
</thead>
<tbody>{renderTable()}</tbody>
</table>
</div>
);
};
Here You can use this , No Error will occured
const renderTable = () => {
return data && data.length > 0 && data.map((user, i) => {
return (
<tr key={i}>
<td>{user.show?.name}</td>
<td>{user.show?.language}</td>
<td>{user.show?.genres}</td>
<td>{user.show?.runtime}</td>
<td>{user.show?.premiered}</td>
<td>{user.show?.rating?.average}</td>
<td>{user.show?.network?.country?.name}</td>
<td>
<img src={user?.show?.image?.medium} alt="poster" />
</td>
</tr>
);
});
};
I think the problem is in api and also the id here
const url = `https://api.tvmaze.com/shows/${id}
where have you declared the id ? and to make sure that the data is coming fine before using it first console.log() the response data and see what you get and open the network tab to see the reason of the error clearly

Why is my data not displaying in the table in react

Does anyone know why my data isn't displaying, it console.logs 'x[0]', 'x[1]', 'x[2]', and 'x[3]' fine in my return statement. I'm pretty new to react and programming in general so I have no idea why this doesn't work.
I would just expect it to fill the rows of the table like the 2 I've manually coded in.
import React, { useState, useEffect } from 'react'
import "./stylesheets/oddsmatcher-table.css"
const App = () => {
const [wow, setWow] = useState([])
useEffect(() => {
fetch(DATA)
.then(res => res.json())
.then(data => {
const newData = data.data.slice(0, 10)
const k = newData.map(x => {
return [x.date, x.event_name, x.bookmaker_name, x.exchange]
})
setWow(k)
console.log(k)
})
}, [])
return(
<table>
<tbody>
<tr>
<th>Date</th>
<th>Event</th>
<th>Bookie</th>
<th>Exchange</th>
</tr>
<tr>
<td>25-09-2020</td>
<td>Man United vs Liverpool</td>
<td>Bet365</td>
<td>Smarkets</td>
</tr>
<tr>
<td>26-09-2020</td>
<td>Arsenal vs Man City</td>
<td>Coral</td>
<td>Betfair Exchange</td>
</tr>
{wow.forEach(x => {
return(
<tr>
<td>{x[0]}</td>
<td>{x[1]}</td>
<td>{x[2]}</td>
<td>{x[3]}</td>
</tr>
)
})}
</tbody>
</table>
)
}
export default App
Update: Try switching your wow.forEach to this:
{wow.map((x, index) => {
return (
<tr key={index}>
{x.map((dataPiece) => (
<td key={dataPiece}>{dataPiece}</td>
))}
</tr>
);
})}
Here's the Codesandbox I was using to test. I replaced your async fetch with a global variable with what I think your wow data looks like:
https://codesandbox.io/s/suspicious-glitter-mf0tg?fontsize=14&hidenavigation=1&theme=dark
Let me know if that works. If it doesn't, can you post an example of what your fetched data looks like?

REACT: Instead of sorting by clicking a button - sorting by clicking header "id" in table

I make request to server and I get response. Response it data which I display in view table-list. Also now I try implement when I click button changeAsc happen sort by asc-desc.
But I need that sort by asc-desc was happening when I click on header header id in table. And display the word asc or desc to the right of the header id. Table I export in file Home.js from file - Table.js.
What I need to change in file Table.js that implement sort when I click to header id?
Home.js:
import Table from "./Table/Table.js";
const Home = () => {
const [value, setValue] = useState({
listCategory: [],
sortAscDesc: "asc",
});
useEffect(() => {
async function fetchData(sortAscDesc) {
const res = await api('api/categories', sortAscDesc);
/....
}
fetchData(value.sortAscDesc);
}, [value.sortAscDesc]);
const changeSortAscDesc = () => {
setValue((prev) => ({
...prev,
sortAscDesc: prev.sortAscDesc == 'asc' ? 'desc' : 'asc'
}));
};
return (
<div>
<Table dataAttribute={value.listCategory}/>
// I WANT DELETE THIS BUTTON: - BECAUSE I WANT SORT BY HEADER "id"
<button onClick={() => changeSortAscDesc()}>changeAsc</button>
</div>
);
};
Table.js:
export default ({dataAttribute}) => (
<table className="table">
<thead className="table-head">
<tr>
<th>id</th> //I WANT SORT WHEN I CLICK ELEMENT id
<th>title</th>
<th>created_at</th>
</tr>
</thead>
<tbody>
{dataAttribute.map(item => (
<tr key={item.id}>
<td>{item.id}</td>
<td>{item.title}</td>
<td>{item.created_at}</td>
</tr>
))}
</tbody>
</table>
);
You can try like this:
<Table dataAttribute={value.listCategory} changeSortAscDesc={changeSortAscDesc} />
In your Table.js
export default (props) => (
<table className="table">
<thead className="table-head">
<tr>
<th onClick={props.changeSortAscDesc}>id</th> //I want sort when I click by element id
<th>title</th>
<th>created_at</th>
</tr>
</thead>
<tbody>
{props.dataAttribute.map(item => (
<tr key={item.id}>
<td>{item.id}</td>
<td>{item.title}</td>
<td>{item.created_at}</td>
</tr>
))}
</tbody>
</table>
);

React 'this' Context within Method

I am trying to call a Method on a Button click like this (the button is returned within a method itself):
<button onClick={removeClick}>Remove</button>
this is the method i am trying to call
removeClick = event => {
console.log('clicked');
};
im always getting errors like '_this2 is undefined'
i have already tried binding the method in the constructor.
an arrow function within the onClick didn't work as well
removeClick = event => {
console.log('clicked');
};
renderWeather(cityData) {
const name = cityData.city.name;
const temps = cityData.list.map(weather => weather.main.temp - 273.15);
const pressures = cityData.list.map(weather => weather.main.pressure);
const humidities = cityData.list.map(weather => weather.main.humidity);
const { lon, lat } = cityData.city.coord;
return (
<tr key={lon + lat}>
<td>
<GoogleMap lon={lon} lat={lat} />
<span className="city-name">{name}</span>
</td>
<td>
<WeatherChart data={temps} color="red" unit="°C" />
</td>
<td>
<WeatherChart data={pressures} color="orange" unit="hPA" />
</td>
<td>
<WeatherChart data={humidities} color="blue" unit="%" />
</td>
<td>
<button onClick={this.removeClick}>Remove</button>
</td>
</tr>
);
}
render() {
return (
<table className="table table-hover">
<thead>
<tr>
<th>City</th>
<th>Temperature (°C) </th>
<th>Pressure (hPA)</th>
<th>Humidity (%)</th>
<th />
</tr>
</thead>
<tbody>{this.props.weather.map(this.renderWeather)}</tbody>
</table>
);
}
}
const mapStateToProps = ({ weather }) => ({
weather
});
const mapDispatchToProps = {
removeCity
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(WeatherList);
this is how the my component looks like
I hope anyone can help me
try
renderWeather = cityData => {
...
}
and because you are using your clickhandler for a set of data you may want to pass some kind of identifier to it
removeClick = id => event => {
console.log(`Removing data for ${id}`)
}
and call it by
<button onClick={() => {this.removeClick(id)}}>Remove</button>
Try to pass this as a second param to map
<tbody>{this.props.weather.map(this.renderWeather, this)}</tbody>
class Item extends React.Component {
removeClick = event => {
console.log('clicked');
}
renderWeather(cityData) {
return <button onClick={this.removeClick}>Remove</button>
}
render() {
return (
<table className="table table-hover">
<thead>
<tr>
<th>City</th>
<th>Temperature (°C) </th>
<th>Pressure (hPA)</th>
<th>Humidity (%)</th>
<th />
</tr>
</thead>
<tbody>{this.props.weather.map(this.renderWeather, this)}</tbody>
</table>
)
}
}
const weather = [
{
city: {name: '123'}
}
];
ReactDOM.render(
<Item weather={weather} />,
document.getElementById('root')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='root'></div>

Resources