how to get spesific data from api with axios and react js? - javascript

-1
Hi I am new in ReactJS
I want to get a Image with spesific Text in caption from Instagram graph api.For example if caption from image has "yes" word in Instagram then must show in homepage.I try to define Mypost with const myPost = contain yes word but i don't get any return.thank you for your help.
import React,{useState} from 'react'
import axios from 'axios';
import ReactDOM from "react-dom";
function Deneme() {
// component variables go here
const [Posts, setPosts] = useState(null);
const fetchData = async () => {
const response = await axios.get(`https://graph.instagram.com/me/media?fields=id,caption,media_url,permalink,username&access_token=IGQV....`)
setPosts(response.data.data)
};
return (
<div className="Deneme">
<h1>Game of Thrones Posts</h1>
<h2>Fetch a list from an API and display it</h2>
{/* Fetch data from API */}
<div>
<button className="fetch-button" onClick={fetchData}>
Fetch Data
</button>
<br />
</div>
{/* Display data from API */}
<div className="Posts">
{Posts &&
Posts.map((posts, index) => {
const myPost = posts.caption.contains("yes");
const cleanedDate = new Date(posts.released).toDateString();
console.log(cleanedDate)
return (
<div className="posts" key={index}>
<h3>posts {index + 1}</h3>
<h2>{myPost.username}</h2>
<div className="details">
<p>{myPost.caption} </p>
<img className="post_img" src={myPost.media_url} alt="image"/>
</div>
</div>
);
})}
</div>
</div>
);
}
export default Deneme
**
enter code here
**

You are not calling the fetchData function anywhere. Call it when the component first renders with the useEffect hook:
useEffect(() => {
fetchData();
}, []);
More on useEffect: https://reactjs.org/docs/hooks-effect.html

Related

Too slow data fetching in React, leading to annot read properties of undefined error

I have a problem with data displaying. Probably the JSX content is rendering too fast before data is actually fetched from API and that causing the following:
Uncaught TypeError: Cannot read properties of undefined (reading 'name')
I checked with console.log; sometimes it's fetching, sometimes not. Also, when I comment out this {concerts[1].name}, then data is loaded and populated. However, when I run it like in the example below, data is not populating, and I am getting errors.
import React from "react";
import { useEffect, useState } from "react";
import axios from "axios";
export const ConcertNewest = () => {
const [concerts, setConcerts] = useState([]);
useEffect(() => {
const loadConcerts = async () => {
const response = await axios.get("/data/concerts");
setConcerts(response.data);
};
loadConcerts();
}, []);
console.log("concerts: " + concerts.length);
return (
<show>
<h1>Newest concerts </h1>
<div>
<div className="card">
<img src="" style={{ width: 100 }} />
<div className="card-text">
<h4> {concerts[1].name}</h4>
</div>
</div>
</div>
</show>
);
};
The code inside useEffect runs after the JSX is rendered. That's by design. So you are ending up with concerts[1].name while concerts is still empty.
A common way to tackle this is to show some loading indicator while the data is being fetched, like so, for example:
import React from "react";
import { useEffect, useState } from "react";
import axios from "axios";
export const ConcertNewest = () => {
const [concerts, setConcerts] = useState([]);
useEffect(() => {
const loadConcerts = async () => {
const response = await axios.get("/data/concerts");
setConcerts(response.data);
};
loadConcerts();
}, []);
if (!concerts.length) {
return <p>Loading...</p>;
}
return (
<show>
<h1>Newest concerts </h1>
<div>
<div className="card">
<img src="" style={{ width: 100 }} />
<div className="card-text">
<h4> {concerts[1].name}</h4>
</div>
</div>
</div>
</show>
);
};

React, problem with my Todo list app, my search engine only finds notes on the page I'm on

Hello I am making an application to practice React, my notes app has a pagination which works perfectly, the problem is in the search engine, which only looks for notes from the page I'm on, for example, if I'm on page 2 and I look for a note on page 2, it shows it, however if the note is on a different page, it doesn't show it, it doesn't find it.
I know where the problem is but I'm not sure how to solve it, I'm a bit new to React and I was asking for your help.
I was able to do my pagination with the package react-paginate here is the documentation https://www.npmjs.com/package/react-paginate
My code:
Component App.js
import { useState, useEffect } from "react";
import { nanoid } from 'nanoid';
import './App.css';
import Search from "./components/Search";
import Header from "./components/Header";
import Pagination from "./components/Pagination";
const App = () => {
const [notes, setNotes] = useState([]);
const [searchText, setSearchText] = useState('');
const [darkMode, setDarkMode] = useState(false);
const [showNote, setShowNote] = useState(true); //eslint-disable-line
useEffect(() => {
const saveNotes = JSON.parse(localStorage.getItem('notes-data'));
if (saveNotes){
setNotes(saveNotes);
}
}, []);
useEffect(() => {
localStorage.setItem('notes-data', JSON.stringify(notes))
},[notes])
const addNote = (inputText, text) => {
const date = new Date();
const newNote = {
id: nanoid(),
title: inputText,
text: text,
date: date.toLocaleString()
}
const newNotes = [newNote, ...notes];
setNotes(newNotes)
}
const deleteNote = (id) => {
var response = window.confirm("Are you sure?");
if (response){
const notesUpdated = notes.filter((note) => note.id !== id)
setNotes(notesUpdated);
}
}
return (
<div className={darkMode ? 'dark-mode' : ''}>
<div className="container">
<Header
handleToggleTheme={setDarkMode}
/>
<Search
handleSearchNote={setSearchText}
setShowNote={setShowNote}
/>
<Pagination
data={notes}
handleAddNote={addNote}
handleDeleteNote={deleteNote}
searchText={searchText}
/>
</div>
</div>
)
}
export default App;
Component Pagination.js
import React, { useEffect, useState } from 'react'
import ReactPaginate from 'react-paginate';
import '../styles/Pagination.css';
import NoteList from './NoteList';
import { MdSkipPrevious, MdSkipNext } from 'react-icons/md';
const Pagination = (props) => {
const { data, searchText, handleAddNote, handleDeleteNote } = props;
// We start with an empty list of items.
const [currentItems, setCurrentItems] = useState([]);
const [pageCount, setPageCount] = useState(0);
// Here we use item offsets; we could also use page offsets
// following the API or data you're working with.
const [itemOffset, setItemOffset] = useState(0);
const itemsPerPage = 9;
useEffect(() => {
// Fetch items from another resources.
const endOffset = itemOffset + itemsPerPage;
console.log(`Loading items from ${itemOffset} to ${endOffset}`);
setCurrentItems(data.slice(itemOffset, endOffset));
setPageCount(Math.ceil(data.length / itemsPerPage));
}, [itemOffset, itemsPerPage, data]);
// Invoke when user click to request another page.
const handlePageClick = (event) => {
const newOffset = (event.selected * itemsPerPage) % data.length;
console.log(
`User requested page number ${event.selected}, which is offset ${newOffset}`
);
setItemOffset(newOffset);
};
return (
<>
<NoteList
notes={currentItems.filter((noteText) =>
noteText.title.toLowerCase().includes(searchText)
)}
handleAddNote={handleAddNote}
handleDeleteNote={handleDeleteNote}
/>
<div className="pagination-wrapper">
<ReactPaginate
breakLabel="..."
nextLabel={<MdSkipNext
className='icons'
/>}
onPageChange={handlePageClick}
pageRangeDisplayed={3}
pageCount={pageCount}
previousLabel={<MdSkipPrevious
className='icons'
/>}
renderOnZeroPageCount={null}
containerClassName="pagination"
pageLinkClassName="page-num"
previousLinkClassName="page-num"
nextLinkClassName="page-num"
activeLinkClassName="activee boxx"
/>
</div>
</>
);
}
export default Pagination;
Component NoteList.js
import React from 'react'
import Note from './Note'
import '../styles/NoteList.css'
import AddNote from './AddNote'
const NoteList = ({ notes, handleAddNote, handleDeleteNote }) => {
return (
<>
<div className="add-notes-wrapper">
<AddNote
handleAddNote={handleAddNote}
/>
</div>
<div className='notes-list'>
{notes.map((note =>
<Note
key={note.id}
id={note.id}
title={note.title}
text={note.text}
date={note.date}
handleDeleteNote={handleDeleteNote}
/>
))}
</div>
</>
)
}
export default NoteList;
Component Search.js
//import React, { useState } from 'react'
import {MdSearch, MdAdd} from 'react-icons/md'
import '../styles/Search.css'
const Search = ({ handleSearchNote, setShowNote }) => {
const handleShowAddNote = () => {
if (setShowNote){
let addNote = document.querySelector('.new');
addNote.classList.add('wobble-horizontal-top')
addNote.style.display='flex';
document.querySelector('.notes-list').style.display='none';
document.querySelector('.pagination').style.display='none';
}
}
return (
<div className='search'>
<div className="input-wrapper">
<MdSearch
className='icon search-icon'
/>
<input
type="text"
placeholder='What note are you looking for?'
onChange={(event) => handleSearchNote(event.target.value) }
/>
</div>
<div className="btn-wrapper-search">
<button
className='btn-addNote'
onClick={handleShowAddNote}>
Nueva Nota
</button>
<MdAdd
className='icon add-icon'
/>
</div>
</div>
)
}
export default Search
The problem is in the component Pagination.js because I'm filtering the notes on each page with the currentItems variable, if I did it with the data variable it would work, but then it would show all the notes, and I don't want that, I currently want to show 9 notes per page.
greetings and thanks in advance.
Edit:
#Newbie I'm doing what you said, but I don't know if you mean this, in my Pagination.js component I did:
useEffect(() => {
const filterNotes=data.filter((noteText) =>
noteText.title.toLowerCase().includes(searchText)
)
setItemOffset(0);
}, [data, searchText])
It doesn't work, do I have to pass a prop to my components additionally?
greetings.
As I suggested to you, search all the notes with searchText in your App.js and pass the results into the Pagination component and it will solve your problem.
Codesandbox: https://codesandbox.io/s/youthful-thompson-xugs0c
Edit
All changes are as per what we talked about in the email.
Codesandbox: https://codesandbox.io/s/green-fast-3k76wx
Search and pagination do not play well together, one of the common solutions is to jump to page 1 each time the filter term changes.
So use an useEffect on searchText to filter data and reset itemOffset to 0, then redo pagination as if the data changed.
The user will jump to page 1 at each keystroke of the search, then he can navigate pages (if there are more than one). This will lead to a less confusing UX.

React is rendering before api data arrived

i have an ojbect inside an object and i want to extract the sub object to map it but the component is readered before the data is arrived
the main object name is Movie and the sub object is Categories
and i want to map Categories but it says undefind.
import Card from '../UI/Card';
import classes from './MovieDetails.module.css';
import MovieCategoris from './MovieCategories';
import ReactPlayerProps from "react-player";
const MovieDetails = (props) => {
const Movie = props.Movie
const image = Movie.Image;
const Categories = Movie.Categories
const videoSrc = Movie.Video;
return (
<Card>
<div className={classes.VideoPlayer}>
<ReactPlayerProps
controls
volume={1}
muted={false}
width={"100%"}
height={"100%"}
url={videoSrc}
/>
</div>
<div className={classes.DetailsBox}>
<div className={classes.Details}>
<div className={classes.Title}>
<img src={image} />
</div>
<div className={classes.MovDet}>
<h3>{Movie.Title}</h3>
<ul>
<li>Duration: <label>{Movie.Duration}</label></li>
<li>Quality: <label>HD 720</label></li>
<li>release date: <label>{Movie.Year}</label></li>
<li>IMBb: <label>{Movie.Rate}</label></li>
</ul>
<h5>Categories</h5>
{/* <div>
<ul className={classes.Cat_li}>
{Categories.map((cat) =>
<li>{cat}</li>
)}
</ul>
</div> */}
</div>
<div className={classes.Desc}>
<p> {Movie.Description} </p>
</div>
</div>
</div>
</Card>
)
}
export default MovieDetails;
this is the function that get the api data and forward it with props to the component.
import MovieDetails from "../components/Content/MovieDetails";
import { useParams } from "react-router-dom";
import { useEffect, useState } from "react";
import FetchedMovie from '../Hooks/fetchSingleMovie'
const MovieDetailsPage = () => {
const [MovieData, setMovieData] = useState([])
const MovieId = useParams()
async function Movie(MovieId) {
const id = MovieId.movie
const result = await FetchedMovie(id)
setMovieData(result)
return result
}
useEffect(() => {
Movie(MovieId)
}, [])
return <MovieDetails Movie={MovieData} />
}
export default MovieDetailsPage;
this is the object i have on the api sever
That's because you ara passing an empty array in your MovieDetails component in MovieDetailsPage
you can render MovieDetails whene your data is ready
Try to change it in something like this
import MovieDetails from "../components/Content/MovieDetails";
import { useParams } from "react-router-dom";
import { useEffect, useState } from "react";
import FetchedMovie from '../Hooks/fetchSingleMovie'
const MovieDetailsPage = () => {
const [MovieData, setMovieData] = useState(null)
const MovieId = useParams()
async function Movie(MovieId) {
const id = MovieId.movie
const result = await FetchedMovie(id)
setMovieData(result)
return result
}
useEffect(() => {
Movie(MovieId)
}, [])
return MovieData && <MovieDetails Movie={MovieData} />
}
export default MovieDetailsPage;
it happens because the api will render after your first moviedetails call;
you can use an if before your map that everytime its defined, map the function like this: {categories && categories.map ... }; because everytime that the props changes page will rerender;

How can I return text with useState?

I am waiting for the data (when the user submit) i fetch the data then return the Temperature with useState() but i wanted to return a header with it like Temperature:12°C.
Something else is that i wanna round the temperature to 2 decimal places but i don't know how to do so
here is my code:
import axios from 'axios';
import React from 'react'
import {useState, useEffect} from 'react'
import './style.css'
import rain from './use1.png'
function App() {
const [name,setName] = useState('Cairo')
const [res, setRes] = useState(null)
const [pic, setPic] = useState(null)
const [temp, setTemp] = useState('')
const getApi = e => {
axios.get(`https://api.openweathermap.org/data/2.5/weather?q=${name}&appid=my_key`)
.then(response=> {
console.log(response.data);
setRes(response.data.name)
setTemp(response.data.main.feels_like-273.15+'°C');
Math.round(temp)
setPic(`https://openweathermap.org/img/w/${response.data.weather[0].icon}.png`)
})}
const handleChange = e => {
setName(e.target.value);
};
return (
<div>
<img className="wallpaper" src={rain}></img>
<div className="content">
<input placeholder="Search.." className="input" onChange={handleChange}></input>
</i>
</div>
<div className="content2">
<h1 className="name">{res}</h1>
<img src={pic}></img>
<h1 className="temp">{temp}</h1>
</div>
</div>
);
}
export default App;
Add a useEffect hook so your component re-renders after your temp state changes.
useEffect(() => {}, [temp]);
In order to round to two decimal places...well, usually I don't like telling people this but that's an extremely easy thing to find out from just using Google or another search engine.
JavaScript math, round to two decimal places
You could do it like:
`Temperature ${(response.data.main.feels_like-273.15).toFixed(2)} °C`
You can do like this
const [temp, setTemp] = useState('')
setTemp(response.data.main.feels_like-273.15+'°C');
return (
<div>
<h1 className="temp"> Temperature {temp?.toFix(2)}</h1>
</div>
)
Could you please provide the full component's code, or at least where is response coming from? Anyway, If the response is being passed from a parent component, then I see no reason to use useState at all.
But if you are fetching the data in the same component, then you need to fetch the data asynchronously:
function component(){
const [temp, setTemp] = useState('Loading temperature...')
useEffect(() => {
fetchTemp().then((response) => {
setTemp(response.data.main.feels_like-273.15+'°C');
})
}, [])
return (
<div>
<h1 className="temp">{temp}</h1>
</div>
)
}
About rounding the number, you can use toFixed(decimals) method.
Example:
let number = 900.1234
console.log(number.toFixed(2))

Validation failed for parameter 'id'. Invalid number?

I'm connecting my Node backend(connected the database using Microsoft SQL Server) to React front-end. Note: The backend works great and tested with postman for all endpoints.
While connecting to it, throws me this error : "Validation failed for parameter 'id'. Invalid number."
App.js
import React, { useState, useEffect } from "react";
import axios from "axios";
import './App.css';
import Header from "./components/Header";
import Search from "./components/Search";
import Events from "./components/Events";
const App = () => {
const [customers, setCustomers] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [searchQuery, setSearchQuery] = useState("");
useEffect(() => {
const fetchEvents = async () => {
const res = await axios(
`http://localhost:8080/api/event/${setSearchQuery}`
);
console.log(res.data);
setCustomers(res.data);
setIsLoading(false);
};
fetchEvents();
}, [searchQuery]);
return (
<div className="container">
<Header />
<Search getQuery={(sq) => setSearchQuery(sq)} />
<Events isLoading={isLoading} customers={customers} />
</div>
);
};
export default App;
Event.js
import React from "react";
const Event = ({ customer }) => {
return (
<div className="card">
<div className="card-inner">
<div className="card-front">
<img src={customer.img} alt="" />
</div>
<div className="card-back">
<h1>{customer.id}</h1>
<ul>
<li>
<strong>Customer ID:</strong> {customer.id}
</li>
<li>
<strong>Customer Number:</strong> {customer.Cus_no}
</li>
<li>
<strong>Range Name:</strong> {customer.RangeName}
</li>
<li>
<strong>Color:</strong> {customer.Color}
</li>
<li>
<strong>Blade Text:</strong> {customer.BladeTExt}
</li>
<li>
<strong>Special Notes:</strong> {customer.SpecialNotes}
</li>
<li>
<strong>Box Quantity:</strong> {customer.box_qty}
</li>
</ul>
</div>
</div>
</div>
);
};
export default Event;
Events.js
import React from "react";
import Event from "./Event";
import Spinner from "./Spinner.js";
const Events = ({ customers, isLoading }) => {
return isLoading ? (
<Spinner />
) : (
<section className="cards">
{customers.map((customer) => (
<Event key={customer.id} customer={customer}></Event> //key={customer.id}
))}
</section>
);
};
export default Events;
Search.js
import React, { useState } from "react";
const Search = ({ getQuery }) => {
const [number, setNumber] = useState(0);
const onChange = (sq) => {
setNumber(sq);
getQuery(sq);
};
return (
<section className="search">
<form>
<input
type="Number"
className="form-control"
placeholder="Search Customer Numbers"
value={number}
onChange={(e) => onChange(e.target.value)}
autoFocus
/>
</form>
</section>
);
};
export default Search;
For better understanding here is a Sample SQL Table output with the data types I created : https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=c925fb80326b4c3ed2117beddb73b451
Now comes the great part, whenever I use the endpoint "http://localhost:8080/api/events" the whole customer data set displays correctly as it supposed to. But for the endpoint "http://localhost:8080/api/event/${setSearchQuery}" it gives me the error.
I think your problem is here:
const [searchQuery, setSearchQuery] = useState("");
your backend API for fetching event needs an id for it and when every your component mounts to the dom, your useEffect kicks in and calls the API! but meanwhile your state of searchQuery is an empty string!
NOTE:
const res = await axios(
`http://localhost:8080/api/event/${setSearchQuery}`
);
you are using setSearchQuery in your endpoint string instead of searchQuery!
that being said, I think still you will get an error even after changing that bug in your URL! because you still send an empty string as id for your backend API!
So the best solution would be to provide a default id for your searchQuery in your useState instead of passing an empty string, or if you cannot provide a default value, make sure that your api does not broke when you providing empty string to it!

Categories

Resources