where is the error and what should need to change can you explain. After the cart.map props can not read the property name and others. it just read it as an array . when i do console.log(props.product) then in console tab show all added product but when i want to read the name,price and others it cannot it just read only quantity.
i added picture of the console tab please check it.
now what is the problem of that code
please help me out
**Review.js
**
import React, { useEffect, useState } from 'react';
import { getDatabaseCart } from '../../utilities/databaseManager';
import fakeData from '../../fakeData';
import ReviewItem from '../ReviewItem/ReviewItem';
import Cart from '../Cart/Cart';
const Review = () => { const [cart, setCart] = useState([]);
useEffect(()=>{
//cart
const savedCart = getDatabaseCart();
const productKeys = Object.keys(savedCart);
const cartProducts = productKeys.map( key => {
const product = fakeData.filter( pd => pd.key === key);
product.quantity = savedCart[key];
return product;
});
setCart(cartProducts);
}, []);
return (
<div className="twin-container">
<div className="product-container">
{
cart.map(pc => <ReviewItem
key={pc.key}
product={pc}></ReviewItem>)
}
</div>
</div>
);
};
export default Review;
reviewItem.js
import React from 'react';
const ReviewItem = (props) => {
const {name,price,quantity} = props.product;
const reviewItemStyle={
borderBottom:'1px solid lightgray',
marginBottom:'5px',
paddingBottom:'5px',
marginLeft:'200px'
};
console.log(name);
return (
<div style={reviewItemStyle} className="review-item">
<h4 className="product-name">Name:{name}</h4>
<p>Quantity: {quantity}</p>
<p><small>$ {price}</small></p>
<br/>
</div>
);
};
export default ReviewItem;
Related
where was the problem to those code, the review page cannot read the properties and it shows blank page when called name & others but in the java script output it show on console tab. when i called any properties of the product data output should be blank.
please help me out!
i added the screen shot of the error and output on server.
[enter image descriptionenter image description hereon here](https://i.stack.imgur.com/XEvLs.png)
Review.js
import React, { useEffect, useState } from 'react';
import fakeData from '../../fakeData';
import {getDatabaseCart} from '../../utilities/databaseManager';
import ReviewItem from '../ReviewItem/ReviewItem';
const Review = () => {
const [cart, setCart] = useState([]);
useEffect(()=>{
//cart
const savedCart = getDatabaseCart();
const productKeys = Object.keys(savedCart);
const cartProducts = productKeys.map( key => {
const product = fakeData.find( pd => pd.key === key);
return product;
});
setCart(cartProducts);
}, []);
return (
<div>
<h1>Cart Item : {cart.length}</h1>
{
cart.map(pd => <ReviewItem
key={pd.key}
product={pd}></ReviewItem>)
}
</div>
);
};
export default Review;
ReviewItem.js
import React from 'react';
const ReviewItem = (props) => { const {name, quantity, price} = props.product;
return (
<div >
<h4 >{name}</h4>
<p>Quantity: {quantity}</p>
<p><small>$ {price}</small></p>
</div>
);
};
export default ReviewItem;
Please help me out to show the details on review tab
it seems like the line :
const product = fakeData.find( pd => pd.key === key);
is the problem ,
where "fakeData" is an array and you are trying to access the property "key" from "pd" which does not exist , you should review "fakeData" or the exported array from it's file
I would like to use useEffect()to instead of componentWillMount(), but I found the hook can not use in class components, so I change the code as Function component, but it will get more error for the whole component, all code with this.xxx are getting an error, how could I edit below code to make it work? Please help me. Below code is working fine with componentWillMount().
import React, { Component } from 'react';
import './index.less';
import { formateDate } from '../../utils/dateUtils';
import memoryUtils from '../../utils/memoryUtils';
import { reqWeather } from '../../api/index';
import { withRouter } from 'react-router-dom';
import menuList from '../../config/menuConfig';
class Header extends Component {
state = {
currentTime: formateDate(Date.now()),
dayPictureUrl: '',
weather: '',
};
getTime = () => {
setInterval(() => {
const currentTime = formateDate(Date.now());
this.setState({ currentTime });
}, 1000);
};
getWeather = async () => {
const { dayPictureUrl, weather } = await reqWeather('Auckland');
this.setState({ dayPictureUrl, weather });
};
getTitle = (props) => {
const path = this.props.location.pathname;
let title;
menuList.forEach(item => {
if (item.key === path) {
title = item.title;
} else if (item.children) {
const cItem = item.children.find(cItem => cItem.key === path);
if (cItem) {
title = cItem.title;
}
}
});
return title;
};
componentDidMount() {
this.getTime();
this.getWeather();
}
render() {
const { currentTime, dayPictureUrl, weather } = this.state;
const username = memoryUtils.user.username;
const title = this.getTitle();
return (
<div className="header">
<div className="header-top">
<span>Welcome, {username}</span>
<a href>logout</a>
</div>
<div className="header-bottom">
<div className="header-bottom-left">{title}</div>
<div className="header-bottom-right">
<span>{currentTime}</span>
<img src={dayPictureUrl} alt="weather" />
<span>{weather}</span>
</div>
</div>
</div>
);
}
}
export default withRouter(Header)
I've converted from react classes to react hooks I hope it help, I haven't tested because I don't have the external files that you have but I hope it helps otherwise just comment on this solution ;)
import React, { useState, useEffect } from 'react';
import './index.less';
import { formateDate } from '../../utils/dateUtils';
import memoryUtils from '../../utils/memoryUtils';
import { reqWeather } from '../../api/index';
import { withRouter, useLocation } from 'react-router-dom';
import menuList from '../../config/menuConfig';
function Header(){
const [currentTime, setCurrentTime] = useState(formateDate(Date.now()))
const [dayPictureUrl, setDayPictureUrl] = useState('')
const [weather, setWeather] = useState('')
const location = useLocation();
const path = location.pathname;
useEffect(() => {
getTime();
getWeather();
},[]);
const getTime = () => {
setInterval(() => {
const currentTime = formateDate(Date.now());
setCurrentTime(currentTime)
}, 1000);
};
const getWeather = async () => {
const { dayPictureUrl, weather } = await reqWeather('Auckland');
setDayPictureUrl(dayPictureUrl)
setWeather(weather)
};
const getTitle = (props) => {
let title;
menuList.forEach(item => {
if (item.key === path) {
title = item.title;
} else if (item.children) {
const cItem = item.children.find(cItem => cItem.key === path);
if (cItem) {
title = cItem.title;
}
}
});
return title;
};
const username = memoryUtils.user.username;
const title = getTitle();
return (<div className="header">
<div className="header-top">
<span>Welcome, {username}</span>
<a href>logout</a>
</div>
<div className="header-bottom">
<div className="header-bottom-left">{title}</div>
<div className="header-bottom-right">
<span>{currentTime}</span>
<img src={dayPictureUrl} alt="weather" />
<span>{weather}</span>
</div>
</div>
</div> )
}
export default Header
Here's my go at converting the function to using hooks.
One of the best things about hooks is that they can all be called as many times as you like, which allows us to separate the concerns of a component into logical blocks.
useEffect shouldn't be considered a direct replacement for componentDidMount as it works differently. The closest would actually be useLayoutEffect because of the timing of it matches componentDidMount and componentdDidUpdate. More detail on the difference between the two: useEffect vs useLayoutEffect. Although you should in general use useEffect primarily.
Getting used to hooks requires a bit of a shift in how you think of components, but in my opinion, it's worth the effort to switch!
import React, {useEffect, useMemo, useState} from 'react';
import './index.less';
import { formateDate } from '../../utils/dateUtils';
import memoryUtils from '../../utils/memoryUtils';
import { reqWeather } from '../../api/index';
import { useLocation } from 'react-router-dom';
import menuList from '../../config/menuConfig';
export default function Header (props){
const [currentTime, setCurrentTime] = useState(formateDate(Date.now()));
useEffect(()=>{
const intervalId = setInterval(()=>{
setCurrentTime(formateDate(Date.now()));
},1000)
// Make sure to cleanup your effects!
return ()=>{clearInterval(intervalId)}
},[])
const [dayPictureUrl, setDayPictureUrl] = useState('');
const [weather, setWeather] = useState('');
useEffect(() => {
const getWeather = async () => {
const { dayPictureUrl, weather } = await reqWeather('auckland');
setDayPictureUrl(dayPictureUrl);
setWeather(weather);
};
// Assuming that we want to have the weather dynamically based on a passed in prop (i.e. props.city), or a state.
getWeather();
}, []);
// useLocation gets the location via a hook from react router dom
const location = useLocation();
const title = useMemo(()=>{
// useMemo as this can be an expensive calculation depending on the length of menuList
// menuList is always a constant value, so it won't change
const path = location.pathname;
let title;
menuList.forEach(item => {
if (item.key === path) {
title = item.title;
} else if (item.children) {
const cItem = item.children.find(cItem => cItem.key === path);
if (cItem) {
title = cItem.title;
}
}
});
return title;
},[location.pathname])
const username = memoryUtils.user.username;
return (
<div className="header">
<div className="header-top">
<span>Welcome, {username}</span>
<a href>logout</a>
</div>
<div className="header-bottom">
<div className="header-bottom-left">{title}</div>
<div className="header-bottom-right">
<span>{currentTime}</span>
<img src={dayPictureUrl} alt="weather" />
<span>{weather}</span>
</div>
</div>
</div>
);
}
I'm trying to pass an array of data as props (using context) to another component Carousello.js
But I’m unable to retrieve data on my Home.js component.
This is My HomeContext.js Component:
I use context to calling the API and then passing data to Home.js
import React, { useState, createContext } from 'react';
import axios from 'axios'
export const HomeContext = createContext();
export const HomeProvider = (props) => {
let array = []
axios.get(`/wordpress/wp-json/wp/v2/pages/15`)
.then(function (res) {
let slider = res.data.acf.slider
array.push(slider)
})
console.log(typeof (array))
let ar = array.flat()
console.log(ar)
return (
<HomeContext.Provider value={[array]}>
{props.children}
</HomeContext.Provider>
)
}
This is my Carosello.js component where i try to retrive data and render it with jsx:
import React, { Component, useContext } from 'react'
import sfondo from './sfondo-gray.jpg'
import { HomeProvider, HomeContext } from './HomeContext';
const Carosello = () => {
const [acf] = useContext(HomeContext)
console.log(acf)
return (
<div id="myCarousel" className="carousel slide" data-ride="carousel" >
<h1> {acf.title} </h1>
</div >
)
}
export default Carosello
You probably also need to wrap your axios call in a function to use inside useEffect. For more detailed info on that, check these: A complete guide to useEffect and fetchind data with useEffect. Basically, using the [] (empty list of dependencies) to trigger one-time action doesn't always work as you would expect from class components' componentDidMount.
export const HomeProvider = (props) => {
const [array, setArray] = useState([]);
useEffect(()=> {
function fetchData() {
axios.get(`/wordpress/wp-json/wp/v2/pages/15`)
.then(function (res) {
let slider = res.data.acf.slider
setArray([...slider.flat()])
})
}
fetchData();
}, [])
return (
<HomeContext.Provider value={[array]}>
<>{props.children}</>
</HomeContext.Provider>
)
}
import React, { useState, createContext } from 'react';
import axios from 'axios'
export const HomeContext = createContext();
export const HomeProvider = ({children}) => {
// array type
const [items, setItems] = useState([])
axios.get(`/wordpress/wp-json/wp/v2/pages/15`)
.then(function (res) {
let slider = res.data.acf.slider
setItems([...slider.flat()])
})
return (
<HomeContext.Provider value={{
array:items
}}>
{children}
</HomeContext.Provider>
)
}
const Carosello = () => {
// object destructuring
const {array} = useContext(HomeContext)
return (
<div id="myCarousel" className="carousel slide" data-ride="carousel" >
{/* if is array, try to map or [key] */}
<h1> {array[0].title} </h1>
</div >
)
}
export default Carosello
`
function HomeProvider(){
const [array, setArray] = React.useState([]);
React.useEffect(()=> {
axios.get(`/wordpress/wp-json/wp/v2/pages/15`)
.then(function (res) {
let slider = res.data.acf.slider
setArray((arr)=> [...arr, slider])
})
}, [])
return (
<HomeContext.Provider value={[array]}>
{props.children}
</HomeContext.Provider>
)
}
Hey everyone pretty new to React hooks. I am simply trying to set some reviews that I retrieve from Firebase but cant seem to get it working. I tried a few solutions and I am struggling to get it working any help would be appreciated.
import React, {useContext, useEffect, useState} from 'react';
import firebase from "firebase";
import ReviewsContext from "./review-context";
const Reviews = () => {
const db = firebase.firestore();
let reviews = useContext(ReviewsContext);
let [reviewsLoaded, setReviewsLoaded] = useState(false);
function getReviews(){
db.collection('reviews')
.get()
.then((snapshot) => {
let dataArray = [];
snapshot.docs.forEach(doc => {
dataArray.push(doc.data());
});
reviews = dataArray;
setReviewsLoaded(true);
console.log('reviews', reviews); // logs the correct amount of reviews
})
}
function renderReviews() {
console.log('renderReviews reviewsLoaded', reviewsLoaded); // is true
console.log('renderReviews reviews length', reviews.length); // is 0
if(reviewsLoaded) {
reviews.map((data) => {
return (
<li key={data.name}>
<h3>{data.name}</h3>
<p>{data.position}</p>
</li>
)
});
}
else {
return false
}
}
useEffect(() => {
getReviews(); // this seems to fire before renderReviews
}, []);
return (
<div>
<ul>
{renderReviews()}
</ul>
</div>
)
};
export default Reviews;
In this case, the context should be stateful. The way you're doing it currently won't work since context on render will always revert to reviews being empty. Your Provider component that gives that ReviewContext should be patterned like below.
import React, { createContext, useState } from "react"
const ReviewContext = createContext()
const ReviewProvider = ({children}) => {
const [reviews, setReviews] = useState([])
return (
<ReviewContext.Provider value={{
reviews: reviews,
setReviews: reviews => setReviews(reviews),
}}>
{children}
</ReviewContext.Provider>
)
}
export default ReviewProvider
export { ReviewContext }
Now, you may do const { reviews, setReviews } = useContext(ReviewContext); Just call setReviews whenever you want to update reviews in the context.
It's actually stated in the docs as well as I searched it. https://reactjs.org/docs/context.html#dynamic-context
I am trying to learn how to use API's in react. I am making a search input for country names using the Rest countires API. I am getting data from https://restcountries.eu/rest/v2/all but I do not know how to handle this data as I can not use map on an object.
import axios from "axios";
import React, { useEffect, useState } from "react";
const App = () => {
const [countries, setCountries] = useState([]);
const [searchName, setSearchName] = useState("");
useEffect(() => {
axios.get("https://restcountries.eu/rest/v2/all").then(response => {
setCountries(response.data);
});
}, []);
const handleSearch = event => {
setSearchName(event.target.value);
};
return (
<div>
<div>
find countries <input onChange={handleSearch} />
</div>
<div></div>
</div>
);
};
export default App;
Expected to list countries after typing such as : sw = Botswana, Swaziland, Sweden ...
From the question it seems like, these are requirements of your app -
1
you need to search by country name
As you type in, list of countries matching the search should be displayed.
I created this sandbox with the code you provided - https://codesandbox.io/embed/58115762-rest-countries-o638k.
It shows a pair of country name and its capital as you enter input in the search box.
This is how I changed your code:
You need to search countries? - Use search API with country name as value of text input - searchName
https://restcountries.eu/rest/v2/name/${searchName}
To display the output with countries matching your search keyword - map over countries and get appropriate keys. Pass those keys as props to your newly created Country component.
Note, I did not need to change how you handled the JSON response. The searchName and countries are the only two state variables used to render the UI.
you will need to render countries after fetching from ajax request as like :
import axios from "axios";
import React, { useEffect, useState } from "react";
const App = () => {
const [countries, setCountries] = useState([]);
const [searchName, setSearchName] = useState("");
useEffect(() => {
axios.get("https://restcountries.eu/rest/v2/all").then(response => {
setCountries(response.data);
});
}, []);
const handleSearch = event => {
setSearchName(event.target.value);
};
return (
<div>
<div>
find countries <input onChange={handleSearch} />
</div>
<ul>
{(countries.length<=0)?"":
countries.map(country=> <li>country.name</li> )
}
</ul>
</div>
);
};
export default App;
I think this is what you are looking for.
If you have got questions, dont hesitate to ask :)
import axios from "axios";
import React, { useEffect, useState } from "react";
const App = () => {
const [countries, setCountries] = useState([]);
const [searchName, setSearchName] = useState("");
useEffect(() => {
axios.get("https://restcountries.eu/rest/v2/all").then(response => {
setCountries(response.data);
});
}, []);
const handleSearch = event => {
let str = event.target.value;
let filteredCountries = countries.filter((country) => country.name.toLowerCase().includes(str.toLowerCase()));
setCountries(filteredCountries);
setSearchName(str);
};
return (
<div>
<div>
find countries <input onChange={handleSearch} />
</div>
<ul> {(countries.length <= 0) ? "" : countries.map(country => <li>{country.name}</li>) } </ul>
</div>
);
};
export default App;
data =[your array];
countryList = data.map(data=>data.name)
console.log(countryList)