Weather Api with React - reactjs

I am quite new to React so I have a simple question I think. I am trying to take the weather description from the API and according to that, I am trying to show different images. I wrote a function getForecast and response.data.weather[0].description turns the right value. So according to that, I am assigning 'image' to different SVG's but in doesnt turn right.
import React, { useState } from 'react';
import axios from 'axios';
import './Products.css';
import ProductItem from './ProductItem';
import Weather from './Weather';
import { Container, Row, Col } from 'react-bootstrap';
function Products() {
const [imageTemp, setImage] = useState('images/umbrella.svg');
const getForecast = () => {
axios({
method: "GET",
url: 'http://api.openweathermap.org/data/2.5/weather?q=Kaunas&appid=7e6e14c967d752abbafb23a1f251b21c'
})
.then((response) => {
console.log(response.data.weather[0].description);
if (response.data.weather[0].description === "overcast clouds") {
setImage('images/umbrella.svg');
}
else if (response.data.weather[0].description === "clear") {
setImage('images/sunglasses.svg');
}
else {
setImage('images/snowflake.svg');
}
})
.catch((error) => {
console.log(error);
});
};
return (
<div className='products'>
<Container className="products-container">
<h2 className="products__title">Products</h2>
<h6 className="products__subtitle">Offers Today</h6>
<Row>
<Col xs="12" md="6" lg="6">
<Weather
src={imageTemp}
path='/'
/>
</Col>
<Col xs="12" md="6" lg="6">
<ProductItem
src='images/img-2.jpg'
text='The Best Coffee'
path='/'
/>
<ProductItem
src='images/img-3.jpg'
text='Top 100 Books'
path='/'
/>
</Col>
</Row>
</Container>
</div>
);
}
export default Products;
And here is my Weather component:
import React from 'react';
function Weather(props) {
return (
<div className='banner__item'>
<figure className='banner__item__pic-wrap'>
<img
className='banner__item__img'
src={props.src}
/>
</figure>
</div>
);
}
export default Weather;

I think there's not a call for getForecast anywhere.
If you wanna know how to call the function at the time you want, i'll recommend you to look into useEffect hook in detail.

You must use useEffect to call this method(getForecast)... Add this part to your code
useEffect(() => {
getForecast();
}, [imageTemp]);

Related

i can't save data in lcoal storage when i refresh the page

Where is the problem, I can't save data in local storage when i refresh the page and it saved when i clicked but the problem it disappear i used usestate data to keep hook i don't know why i tried all solutions and nothing worked i think the problem released because i use redux and that didn't work well or something else or useeffect didn't work for some reason
import { Button, Col, Container, Row } from "react-bootstrap";
import { useDispatch, useSelector } from "react-redux";
import "./Watchstemp.css"
import { FaEye, FaWindowClose } from "react-icons/fa";
import { addTowatched } from "../rtk/reducers/Watchedslice";
import { clearMovie } from "../rtk/reducers/watchSlice";
import { useEffect, useState } from "react";
function Watchstemp(){
const dispatch = useDispatch()
const posts = useSelector(poster => poster)
const [posters, setPosters] = useState(posts.postSlice)
useEffect(() => {
// storing input name
localStorage.setItem("watchlist", JSON.stringify(posters));
}, [posters]); // Update the dependency array with posters
useEffect(() => {
const data = window.localStorage.getItem('watchlist');
setPosters(data ? JSON.parse(data) : posts.postSlice);
}, []);
return(
<>
<Row>
{
posters.map((post => {
return (
<Col lg={3} md={4} sm={6} key={post}>
<div className="movie-cards">
<div className="overlay">
<img className="img-fluid rounded" src={post} alt={post} />
<div className="inner-card-controls">
<FaEye className="ctrl-btn" onClick={() => dispatch(addTowatched(post))} />
<FaWindowClose className="ctrl-btn" onClick={() => dispatch(clearMovie(post))}/>
</div>
</div>
</div>
</Col>
)
}))
}
</Row>
</>
)
}
export default Watchstemp

React useEffect and onClick button do not work

App.js
import { Container, Row, Col } from "react-bootstrap";
import React, { useState, useEffect } from 'react';
import {person} from "./Data"
import DatesCounts from "./Components/DatesCounts";
import DatesList from "./Components/DatesList";
import DatesAction from "./Components/DatesAction";
function App() {
const [personData, setPersonData] = useState(person)
const onDelet =()=> {
setPersonData([])
}
const onViewData=() => {
setPersonData(person)
}
useEffect(()=>{
setPersonData([])
})
return (
<div className="color-body font">
<Container className="py-5">
<DatesCounts person={person} />
<DatesList person={person} />
<DatesAction deletData={onDelet} viewData={onViewData} />
</Container>
</div>
);
}
export default App;
DatesAction.js
import React from 'react';
import {Row,Col} from 'react-bootstrap';
const DatesAction = ({deletData , viewData}) => {
return (
<Row className=" justify-content-center my-2">
<Col sm="8" className="d-flex justify-content-between">
<button onClick={deletData} className="btn-style p-2">Clear All</button>
<button onClick={viewData} className="btn-style p-2">Show Data</button>
</Col>
</Row>
);
}
export default DatesAction;
I tried to execute useEffect to clear data in the beginning without success.
I also tried to execute onClick buttons Clear All and Show Data without success.
as you see the code is for Dates Reminder the componenets are working but the onClick buttons are not working also the useEffect doesn't work.
you need to send child components personData, instead of person. Since they are receiving the json instead of the useState information
<DatesCounts person={personData} />
<DatesList person={personData} />
To update the state try to use useEffect with dependency on your personData
useEffect(() => {}, [personData])
For setting the initial state, you can use use effect without dependency instead of setting it directly to useState.
useEffect(() => {
setPersonData(person);
}, [])
You don't need a hook especially when dealing with onclick events.
simply have a function which will reset the state and pass it as a prop to child component.
const initialState = { }; //definte initial state.
const [person, setPersons] = useState(initialState);
const resetState = () => {
setPersonState(initialState);
}
//render
<Child onReset={resetState} />
You are missing the dependency array in useEffect but anyway lets improve the performance of your code using React.memo and React.useCallback.
Wrap your function in a React.useCallback so that their reference will be same on next render and will improve some performance but to effectively use useCallback wrap the child component with React.memo
DatesAction.jsx
import React from "react";
import { Row, Col } from "react-bootstrap";
const DatesAction = React.memo(({ deletData, viewData }) => {
return (
<Row className=" justify-content-center my-2">
<Col sm="8" className="d-flex justify-content-between">
<button onClick={deletData} className="btn-style p-2">
Clear All
</button>
<button onClick={viewData} className="btn-style p-2">
Show Data
</button>
</Col>
</Row>
);
});
export default DatesAction;
App.jsx
import { Container, Row, Col } from "react-bootstrap";
import React, { useState, useEffect } from "react";
import { person } from "./Data";
import DatesCounts from "./Components/DatesCounts";
import DatesList from "./Components/DatesList";
import DatesAction from "./Components/DatesAction";
function App() {
const [personData, setPersonData] = useState(person);
const onDelet = React.useCallback(() => {
setPersonData([]);
}, [deps]);
const onViewData = React.useCallback(() => {
setPersonData(person);
}, [deps]);
useEffect(() => {
setPersonData([]);
}, [deps]);
return (
<div className="color-body font">
<Container className="py-5">
<DatesCounts person={person} />
<DatesList person={person} />
<DatesAction deletData={onDelet} viewData={onViewData} />
</Container>
</div>
);
}
export default App;

Not sure what this error means...export 'default' (imported as 'addToCart') was not found in '../actions/cartActions' (possible exports: addToCart)

I am going through a tutorial to learn React, Python, Django, and Redux. I came up with this error and not sure what to do:
export 'default' (imported as 'addToCart') was not found in '../actions/cartActions' (possible exports: addToCart). I do understand useHistory has been decpreciated but am not sure how to change it. So far I have struggled to figure out this error.
CartScreen.js
import React, { useEffect } from "react";
import { Link } from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";
import {
Row,
Col,
ListGroup,
Form,
Image,
Button,
Card,
} from "react-bootstrap";
import Message from "../components/Message";
import addToCart from "../actions/cartActions";
function CartScreen({ match, location, history }) {
const productId = match.params.id;
const qty = location.search ? Number(location.search.split("=")[1]) : 1;
const dispatch = useDispatch();
const cart = useSelector((state) => state.cart);
const { cartItems } = cart;
useEffect(() => {
if (productId) {
dispatch(addToCart(productId, qty));
}
}, [dispatch, productId, qty]);
return (
<Row>
<Col md={8}>
<h1>Shopping Cart</h1>
{cartItems.length === 0 ? (
<Message variant="info">
Your cart is empty <Link to="/"> Go Back</Link>
</Message>
) : (
<ListGroup variant="flush">
{cartItems.map((item) => {
<ListGroup.Item key={item.product}>
<Row>
<Col md={2}>
<Image src={item.Image} alt={item.name} fluid rounded />
</Col>
<Col md={3}>
<Link to={`/product/${item.product}`}>{item.name}</Link>
</Col>
<Col md={2}>${item.price}</Col>
</Row>
</ListGroup.Item>;
})}
</ListGroup>
)}
</Col>
<Col md={4}></Col>
</Row>
);
}
export default CartScreen;
cartActions.js
import axios from 'axios'
import {CART_ADD_ITEM } from '../constants/cartConstants'
export const addToCart = (id, qty) => async (dispatch,getState) =>{
const {data} = await axios.get(`/api/products/${id}`)
dispatch({
type:CART_ADD_ITEM,
payload:{
product:data._id,
name:data.name,
image:data.image,
price:data.price,
countInStock:data.countInStock,
qty
}
})
localStorage.setItem('cartItems',JSON.stringify(getState().cart.cartItems))
}
App.js
import { Container } from 'react-bootstrap'
import { BrowserRouter as Router,Routes, Route } from 'react-router-dom'
import Header from "./components/Header";
import Footer from "./components/Footer";
import HomeScreen from './screens/HomeScreen';
import ProductScreen from './screens/ProductScreen';
import CartScreen from './screens/CartScreen';
function App() {
return (
<Router>
<Header />
<main className="py-3">
<Container>
<Routes>
<Route path="/" element={<HomeScreen />} exact />
<Route path="/product/:id" element={<ProductScreen />} />
<Route path='/cart' element={<CartScreen />} />
<Route path='/cart/:id' element={<CartScreen />} />
</Routes>
</Container>
</main>
<Footer/>
</Router>
);
}
export default App;
In cartActions.js try
const addToCart = (id, qty) => async (dispatch,getState) =>
{...}
export default addToCart
instead of export const addToCart = (id, qty) => async (dispatch,getState) => {...}

Netflix Clone Images won't show in rows

I'm newer to coding and have been creating a Netflix clone with react.
I'm trying to create rows and fetch the images into the rows with the tmdb API.
I have fetched the data into my console but I can't get the images to render on the UI.
I know its the src={} in my in my Row.jsx file.
Can anyone help me with fixing this please, I've tried following the documentation for tmdb and i still couldn't get it to work.
Thanks in advance :)
Row.jsx
import axios from 'axios';
import React, { useState, useEffect } from 'react';
const Row = ({ title, fetchURL }) => {
const [movies, setMovies] = useState([]);
useEffect(() => {
axios.get(fetchURL).then((response) => {
setMovies(response.data.results);
});
}, [fetchURL]);
console.log(movies);
return (
<>
<h2 className="text-white font-bold md:text-xl p-4">{title}</h2>
<div className="relative flex items-center">
<div id={'slider'}>
{movies?.map((item, id) => {
<div className="w-[160px] sm:w-[200px] md:w-[240px] lg:w-[280px] inline-block cursor-pointer relative p-2">
<img
src={`https://image.tmdb.org/t/p/original/${item?.backdrop_path}`}
alt={item?.title}
/>
</div>;
})}
</div>
</div>
</>
);
};
export default Row;
Requests.js
const requests = {
requestPopular: `https://api.themoviedb.org/3/movie/popular?api_key=${key}&language=en-US&page=1`,
requestTopRated: `https://api.themoviedb.org/3/movie/top_rated?api_key=${key}&language=en-US&page=1`,
requestTrending: `https://api.themoviedb.org/3/movie/popular?api_key=${key}&language=en-US&page=2`,
requestHorror: `https://api.themoviedb.org/3/search/movie?api_key=${key}&language=en-US&query=horror&page=1&include_adult=false`,
requestUpcoming: `https://api.themoviedb.org/3/movie/upcoming?api_key=${key}&language=en-US&page=1`,
};
export default requests;
Home.jsx
import React from 'react';
import Main from '../components/Main';
import Row from '../components/Row';
import requests from '../Requests';
const Home = () => {
return (
<>
<Main />
<Row title="Up Coming" fetchURL={requests.requestUpcoming} />
<Row title="Popular" fetchURL={requests.requestPopular} />
<Row title="Trending" fetchURL={requests.requestTrending} />
<Row title="Top Rated" fetchURL={requests.requestTopRated} />
<Row title="Horror" fetchURL={requests.requestHorror} />
</>
);
};
export default Home;

Error : "createSliderWithTooltip is not a function"

Im trying to implement the rc-slider for the web app however the rc-slider tooltip isnt recognized and shows an error of "createSliderWithTooltip is not a function" , which im not sure why .
For implementation of rc-slider i followed the rc-slider documentation which is the same way i have implemeneted in the code of home.js somehow im getting an error in console and nothing shows at all.
Thanks in advance.
Home.js
import React, { Fragment, useEffect , useState } from 'react'
import MetaData from './layouts/MetaData'
import { useDispatch , useSelector } from 'react-redux'
import { getProducts } from '../actions/products'
import Product from './products/Products'
import Loader from './layouts/Loader'
import { useAlert } from 'react-alert'
import Pagination from "react-js-pagination";
import {useParams} from 'react-router-dom'
import Slider from 'rc-slider'
import 'rc-slider/assets/index.css';
const { createSliderWithTooltip } = Slider;**//Error occurs here**
const Range = createSliderWithTooltip(Slider.Range)
const Home = () => {
const [currentPage,setCurrentPage]=useState(1);
const [price,setPrice]=useState([1,1000]);
let params=useParams();
const dispatch= useDispatch();
const alert=useAlert();
const {loading,products,error,productsCount,resPerPage,filteredProductsCount }= useSelector(state=>state.products)
const keyword=params.keyword;
useEffect(() => {
if (error) {
return alert.error("error");
}
dispatch(getProducts(keyword, currentPage));
}, [dispatch, alert, error, currentPage, keyword]);
function setCurrentPageNo(pageNumber) {
setCurrentPage(pageNumber)
}
return (
<Fragment>
{loading ? <Loader>Loading ...</Loader>:(
<Fragment>
<MetaData title={'Buy Electronics , Household Items and Many Others Online'} />
<h1 id="products_heading">Latest Products</h1>
<section id="products" className="container mt-5">
<div className="row">
<Fragment>
<div className="col-6 col-md-3 mt-5 mb-5">
<div className="px-5">
<Range
marks={{
1: `$1`,
1000: `$1000`
}}
min={1}
max={1000}
defaultValue={[1, 1000]}
tipFormatter={value => `$${value}`}
tipProps={{
placement: "top",
visible: true
}}
value={price}
onChange={price => setPrice(price)}
/>
</div>
</div>
</Fragment>
{products.map(product => (
<Product key={product._id} product={product} col={4} />
))}
</div>
</section>
<div className="d-flex justify-content-center mt-5">
<Pagination
activePage={currentPage}
itemsCountPerPage={resPerPage}
totalItemsCount={productsCount}
onChange={setCurrentPageNo}//sets current page no as it changes for state management
nextPageText={'Next'}
prevPageText={'Prev'}
itemClass="page-item"
linkClass="page-link"
/>
</div>
</Fragment>
)
}
</Fragment>
)}
export default Home
Instead of const { createSliderWithTooltip } = Slider;, try this:
const createSliderWithTooltip = Slider.createSliderWithTooltip;
I tried several ways and the only thing that actually worked was downgrading to 9.6.5 rc-slider and now everything is working perfectly
The document hasn't been updated yet since new version. As it seems you want to use Range component, now here the way to do it (thanks to Ashvin-Pal): https://github.com/react-component/slider/issues/825#issuecomment-1084416952
The createSliderWithTooltip has been removed in the new version.
Instead, you can implement your custom handle or tooltip easily like this:
handleRender={renderProps => {
return (
<div {...renderProps.props}>
<SliderTooltip>{round}%</SliderTooltip>
</div>
);
}}
let me know if you have any questions.

Resources