I am new to reactJS. i am expecting the json data to be fetched and displayed according to the options that are clicked. I tested with console.log and the data was being fetched correctly, however when i tried using useState setItems(json), it gives me an error of 'Uncaught TypeError: items.map is not a function'
import './App.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import { useState, useEffect} from 'react';
function App() {
const [option, setOption] = useState('Posts')
const [items, setItems] = useState([])
useEffect(()=> {
fetch(`https://jsonplaceholder.typicode.com/${option}`)
.then(response => response.json())
.then(json => setItems(json))
}, [option])
return (
<div className="App">
<div className='container'>
<div className='menuBar'>
<button onClick={()=> setOption('posts')}>Posts</button>
<button onClick={()=> setOption('users')}>Users</button>
<button onClick={() => setOption('comments')}>Comments</button>
<h2>{option}</h2>
{items.map(item => {
return <pre>{JSON.stringify(item)}</pre>
})}
</div>
</div>
</div>
);
}
export default App;
To make your code fail-safe and easier to debug, you should check if items is an array before using map.
import "./App.css";
import "bootstrap/dist/css/bootstrap.min.css";
import { useState, useEffect } from "react";
function App() {
const [option, setOption] = useState("posts");
const [items, setItems] = useState([]);
useEffect(() => {
fetch(`https://jsonplaceholder.typicode.com/${option}`)
.then(response => response.json())
.then(json => setItems(json));
}, [option]);
return (
<div className="App">
<div className="container">
<div className="menuBar">
<button onClick={() => setOption("posts")}>Posts</button>
<button onClick={() => setOption("users")}>Users</button>
<button onClick={() => setOption("comments")}>Comments</button>
<h2>{option}</h2>
{Array.isArray(items) ? items.map(item => <pre>{JSON.stringify(item)}</pre>) : <pre>{JSON.stringify(items)}</pre>}
</div>
</div>
</div>
);
}
export default App;
Related
I have such a problem. I want to receive a notification after entering a keyword in the input and submitting. If there is a movie, then the movies should be listed, if there is not movies, let the toast notification appear. But the problem, even movies there are still toast works. How can i fix it? I want only when there are no movies for example search results doesnt find any film that toast will come. But toast comes every moment
import React, { useState } from "react";
import axios from "axios";
import { API_KEY } from "../../utils/api";
import MovieItem from "../../components/MovieItem/MovieItem";
import { Button, Input, Form } from "antd";
import "antd/dist/antd.min.css";
import "./Search.scss";
import Loader from "../../components/Loader/Loader";
import { toast } from "react-toastify";
const Search = () => {
const [movies, setMovies] = useState([]);
const [searchTerm, setSearchTerm] = useState("");
const [loading, setLoading] = useState(false);
const fetchSearch = () => {
setLoading(true)
axios
.get(
`https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&language=en-US&query=${searchTerm}&page=1&include_adult=false`
)
.then((res) => res.data)
.then((res) => {
if (!res.errors) {
setMovies(res.results);
setLoading(false)
if (movies.length === 0) {
toast("Movies doesnt find");
}
setSearchTerm("");
console.log("yes");
} else {
setMovies([]);
console.log("no");
}
});
};
const handleChange = (e) => {
setSearchTerm(e.target.value);
};
return (
<>
<div className="search">
<div className="container">
<div className="row">
<div className="col-lg-12 mb-3 mt-3">
<h2>Suggest me</h2>
</div>
<Form onFinish={fetchSearch}>
<Form.Item>
<Input
value={searchTerm}
onChange={handleChange}
placeholder="Search Movies"
/>
</Form.Item>
<Button htmlType="submit">Search</Button>
</Form>
</div>
</div>
</div>
<div className="movies">
<div className="container-fluid">
<div className="row">
{loading
?
<Loader/>
: movies?.map((movie, index) => (
<div className="col-lg-3 p-3" key={index}>
<MovieItem movie={movie} page='top_Rated'/>
</div>
))}
</div>
</div>
</div>
</>
);
};
export default Search;
Problem is solved. Res.results.length was my problem's solution
I just started with React and this is my first project. I added a delete icon. I just want when press it a console log will show some text just for testing and knowing how the props are passing between components. The problem is this text is not showing in the console. Please if anyone can help with that, I would appreciate it.
I have user components, allUser component, home component which included in the app.js
User.js component
import "./User.css";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { faTimes } from "#fortawesome/free-solid-svg-icons";
function User(props) {
return (
<div className="singleUser">
<div className="user">
<div>{props.id}</div>
<div>{props.name}</div>
<div>{props.phone}</div>
<div>{props.email}</div>
</div>
<div className="iconClose">
<FontAwesomeIcon icon={faTimes} onClick={() => props.onDelete} />
</div>
</div>
);
}
import User from "./user";
import { useState, useEffect } from "react";
function Allusers({ onDelete }) {
const [isLoading, setIsLoading] = useState(false);
const [actualData, setActualData] = useState([""]);
useEffect(() => {
setIsLoading(true);
fetch("https://jsonplaceholder.typicode.com/users")
.then((response) => response.json())
.then((data) => {
// const finalUsers = [];
// for (const key in data) {
// const u = {
// id: key,
// ...data[key],
// finalUsers.push(u);
// }
setIsLoading(false);
setActualData(data);
});
}, []);
if (isLoading) {
return (
<section>
<p>Loading ... </p>
</section>
);
}
return actualData.map((singlUser) => {
for (const key in singlUser) {
// console.log(singlUser.phone);
return (
<div className="userCard" key={singlUser.id}>
<User
id={singlUser.id}
name={singlUser.name}
email={singlUser.email}
phone={singlUser.phone}
key={singlUser.id}
onDelete={onDelete}
/>
</div>
);
}
});
}
export default Allusers;
import Navagation from "../components/Navagation";
import Allusers from "../components/Allusers";
import Footer from "../components/Footer";
function Home() {
const deleteHandler = () => {
console.log("something");
};
return (
<section>
<Navagation />
<Allusers onDelete={deleteHandler} />
</section>
);
}
export default Home;
You aren't actually calling the function with () => props.onDelete in User.js-- it needs to be () => props.onDelete() (note the parens added after props.onDelete).
<FontAwesomeIcon icon={faTimes} onClick={() => props.onDelete} />
...should be:
<FontAwesomeIcon icon={faTimes} onClick={() => props.onDelete()} />
I don't quietly undestand when the useState sets initial value. In this code example only on first click props and state values in Table component will be the same. Why they will not be equal on a second/third/fourth click?
import React, { useState } from "react";
import "./App.module.css";
import styles from "./App.module.css";
function App() {
const [mode, setMode] = useState({ bo: false, value: "1" });
const onClickHanlder = (value: string) => {
setMode({ bo: true, value });
};
return (
<div className="App">
<div onClick={() => onClickHanlder("2")}>one</div>
<div onClick={() => onClickHanlder("3")}>one</div>
<div onClick={() => onClickHanlder("4")}>one</div>
<div onClick={() => onClickHanlder("25")}>one</div>
<div onClick={() => onClickHanlder("6")}>one</div>
{mode && <Table value={mode.value} />}
</div>
);
}
export default App;
type TablePropsType = {
value: string
};
export const Table: React.FC<TablePropsType> = (props) => {
const [a, setA] = useState(props.value);
return (
<div>
{a}
{props.value}
</div>
);
};
You never set the state in Table, only on initial render you give it the default state. If you want them to be the same you have to also have to set the state in Table:
import React, {useState, useEffect} from 'react';
function App() {
const [mode, setMode] = useState({bo: false, value: '1'})
const onClickHanlder = (value: string) => {
setMode({bo: true, value})
}
return (
<div className="App">
<div onClick={() => onClickHanlder('2')}>one</div>
<div onClick={() => onClickHanlder('3')}>one</div>
<div onClick={() => onClickHanlder('4')}>one</div>
<div onClick={() => onClickHanlder('25')}>one</div>
<div onClick={() => onClickHanlder('6')}>one</div>
{
mode && <Table value={mode.value}/>
}
</div>
);
}
export default App;
type TablePropsType = {
value: string,
}
export const Table:React.FC<TablePropsType> = (props) => {
const [a, setA] = useState(props.value)
useEffect(()=>{
setA(props.value)
},[props.value])
return (
<div>
{a}
{props.value}
</div>
)
}
I have json data file. I want to make a search with the names of the data and display the typed names when I click the search button.
I get the value of input in the console when I type something however I am not able to display it on the screen
How can I display the value of this input ?
my code is below
PostResults.jsx
import React from "react";
const PostResults = (props) => {
const {name} = props.posts
return(
<div className="">
<p className="titles">{name}</p>
</div>
)
}
export default PostResults
Posts.jsx
import React, { useState, useEffect } from "react";
import PostResults from './PostResults'
const Posts = (props) => {
const [posts, setPosts] = useState([]);
const [searchTerm,setSearchTerm]=useState([]);
const getData = () => {
fetch('data.json')
.then(response => {
return response.json()
//console.log(response)
})
.then(data => {
setPosts(data)
console.log(data)
})
}
useEffect(() => {
getData()
},[])
const submitHandler = (event) => {
event.preventDefault()
{searchTerm ? searchTerm : console.log("none")}
}
return(
<div className="">
<input
type="text"
placeholder="Search Anything"
name="query"
onChange={e => setSearchTerm(e.target.value)}
className="search-input"
/>
<button
onClick={submitHandler}
type="submit"
className="search-button"
>
<i className="fas fa-search"></i>
</button>
{posts.map(posts => (
<PostResults key={posts.id} posts={posts}/>
))}
</div>
)
}
export default Posts
App.jsx
import React from "react";
import "./style.css";
import 'bootstrap/dist/css/bootstrap.min.css'
import Posts from './components/Posts'
export default function App() {
return (
<div className="container">
<div className="row">
< Posts />
</div>
</div>
);
}
So I currently have this code that has a useEffect() that shows the data from the API every time. I refresh, but I'm trying to make that data display only when I click on my button. I'm not too sure where to go with my code.
import React, { useState, useEffect } from 'react';
import './App.css';
import axios from 'axios';
function App() {
const [image, setImage] = useState(false);
// I tried to put a onclick function, but not sure what to add here
const handleChange = ()
=> {
setImage(true)
}
// this code displays my data on refresh
useEffect(() => {
axios
.get(
'https://api.com'
)
.then(res => {
setImage ?
setImage(res.data.faces[0].urls[4][512]) : console.log('nothing')
})
.catch(err => {
console.log(err.message);
});
}, []);
return (
<div className='App'>
<h1>Photo Generator</h1>
<img src={image} />
<button onClick={handleChange}>Show new Image</button>
</div>
);
}
I've updated your code.
Try this code, let me know if it works for you. :)
import React, { useState } from "react";
import "./App.css";
import axios from "axios";
function App() {
const [image, setImage] = useState(false);
// I tried to put a onclick function, but not sure what to add here
const handleChange = () => {
axios
.get("https://api.com")
.then(res => {
const uri = res.data.faces[0].urls[4][512];
if (uri) {
setImage(uri);
} else {
console.log("nothing");
}
})
.catch(err => {
console.log(err.message);
});
};
return (
<div className="App">
<h1>Photo Generator</h1>
{image && <img src={image} alt="yourImage" />}
<button type="button" onClick={handleChange}>
Show new Image
</button>
</div>
);
}
You don't need to use useEffect Hook in this case.
also don't need to check setImage inside of API callback function.
You could do it like this
import React, {useState, useEffect} from 'react';
import './App.css';
import axios from 'axios';
function App() {
const [image, setImage] = useState('');
const [displayImage, setDisplayImage] = useState('none');
const handleChange = () => {
setDisplayImage('flex');
};
useEffect(() => {
axios
.get('https://api.com')
.then((res) => {
setImage
? setImage(res.data.faces[0].urls[4][512])
: console.log('nothing');
})
.catch((err) => {
console.log(err.message);
});
}, []);
return (
<div className="App">
<h1>Photo Generator</h1>
<div style={{display: displayImage}}>
<img style src={image} />
</div>
<button onClick={() => handleChange()}>Show new Image</button>
</div>
);
}
You could also do
<button onClick={() => setDisplayImage('flex')}>Show new Image</button>